Skip to content

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
CoreAspectStu added a commit to CoreAspectStu/autocoder-custom that referenced this pull request Feb 9, 2026
…in AssistantPanel

- Added closeButtonRef to track close button element
- Created handleClose wrapper to blur button before closing
- Prevents ARIA violation when panel closes (focused element inside aria-hidden container)
- Maintains smooth keyboard navigation
- No breaking changes to existing functionality

Accessibility fix verified:
✓ useRef imported and closeButtonRef declared
✓ handleClose function blurs button before onClose
✓ Close button has ref attached
✓ Original onClose callback still called
✓ Properly documented with comments

Resolves console warning: 'aria-hidden element cannot contain focus'
Improves keyboard navigation and screen reader compatibility
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