Skip to content

fix: accept WebSocket before validation to prevent opaque 403 errors#160

Open
nioasoft wants to merge 1 commit intoAutoForgeAI:masterfrom
nioasoft:fix/websocket-403-on-validation
Open

fix: accept WebSocket before validation to prevent opaque 403 errors#160
nioasoft wants to merge 1 commit intoAutoForgeAI:masterfrom
nioasoft:fix/websocket-403-on-validation

Conversation

@nioasoft
Copy link

@nioasoft nioasoft commented Feb 5, 2026

Summary

  • All 5 WebSocket endpoints were closing connections before accept(), causing Starlette to return opaque HTTP 403 errors with no useful information to the client
  • Moved websocket.accept() before all validation checks so errors are sent as JSON messages before clean close with 4xxx codes
  • Client-side hooks now skip reconnection on application-level error codes (4000-4999) to prevent futile retry loops
  • Expand project UI is gated on hasSpec to prevent opening the expand modal when no spec exists

Changes

Server (5 files):

  • expand_project.py - Accept before validation + spec check
  • spec_creation.py - Accept before validation, fix validate_project_name usage
  • assistant_chat.py - Accept before validation, fix validate_project_name usage
  • terminal.py - Accept before all validation checks
  • websocket.py - Accept before validation, ConnectionManager.connect() no longer double-accepts

Client (6 files):

  • useWebSocket.ts / useExpandChat.ts / useSpecChat.ts - Skip reconnection on 4xxx close codes
  • App.tsx - Gate expand shortcut (E key) and modal render on hasSpec
  • KanbanBoard.tsx - Gate expand button on hasSpec
  • KeyboardShortcutsHelp.tsx - Update E key context text

Test plan

  • Open existing project without spec → no 403 errors in server logs
  • Expand button hidden when hasSpec is false
  • E key does nothing when hasSpec is false
  • WebSocket errors show meaningful JSON messages instead of 403
  • No retry loops on application-level close codes

🤖 Generated with Claude Code

All WebSocket endpoints now call websocket.accept() before any
validation checks. Previously, closing the connection before accepting
caused Starlette to return an opaque HTTP 403 instead of a meaningful
error message.

Changes:
- Server: Accept WebSocket first, then send JSON error + close with
  4xxx code if validation fails (expand, spec, assistant, terminal,
  main project WS)
- Server: ConnectionManager.connect() no longer calls accept() to
  avoid double-accept
- UI: Gate expand button and keyboard shortcut on hasSpec
- UI: Skip WebSocket reconnection on application error codes (4000-4999)
- UI: Update keyboard shortcuts help text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nioasoft nioasoft force-pushed the fix/websocket-403-on-validation branch from 035e8fd to dfb102d Compare February 5, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant