Skip to content

fix(view): unusable-board reads surface as JSON 400, not a text/plain 500#60

Merged
mabry1985 merged 1 commit into
mainfrom
fix/board-errors-as-json
Jul 2, 2026
Merged

fix(view): unusable-board reads surface as JSON 400, not a text/plain 500#60
mabry1985 merged 1 commit into
mainfrom
fix/board-errors-as-json

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

The bug

On an agent where the board is unusable — no project_board.repo bound, cwd has no .beads/, br init fails (e.g. a read-only cwd on a desktop-spawned manager) — the board view died with:

Could not load the board: SyntaxError: The string did not match the expected pattern.

GET /features and GET /features/{fid} were the only store-touching routes outside _guard, so the BoardError escaped as FastAPI's text/plain 500 and WebKit's r.json() threw the cryptic parse error instead of showing the (already actionable) message.

The fix

  • api: both GET routes now go through _guard like every other route → JSON 400 carrying the BoardError message ("repo '.' has no beads workspace … set project_board.repo / db_path").
  • view: api() parses defensively — a JSON error body throws its detail, a non-JSON body throws HTTP <status>; load()'s catch renders that. Without this, the JSON 400 would have silently rendered an empty board (r.features || []).

Tests

test_unusable_board_reads_surface_as_json_400_not_500 — a store raising BoardError on reads → both GETs answer 400 JSON with the message. 202 tests pass; ruff check + format clean.

🤖 Generated with Claude Code

… 500

GET /features and /features/{fid} were the only store-touching routes outside
_guard — on an unusable board (no repo bound, no .beads, br missing) the
BoardError escaped as FastAPI's text/plain 500, which the board view could only
render as WebKit's 'SyntaxError: The string did not match the expected pattern'
(r.json() on a non-JSON body). Hit on a manager-tier agent with project_board
enabled but no repo bound.

- api: wrap both GET routes in _guard like every other route — the view now
  receives the actionable BoardError message as JSON 400.
- view: api() parses defensively — a JSON error body surfaces its detail, a
  non-JSON body its HTTP status; load()'s catch renders that instead of a raw
  parse error (previously a 400 would have silently rendered an EMPTY board:
  r.features || [] swallowed the detail).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@protoquinn

protoquinn Bot commented Jul 2, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit 1e40213 into main Jul 2, 2026
1 check passed

@protoquinn protoquinn Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Audit — PR #60 | fix(view): unusable-board reads surface as JSON 400, not a text/plain 500

VERDICT: PASS


CI Status

  • test: success ✅

Diff Review

  • api.py: both GET /features and /features/{fid} now route through _guard, consistent with every other store-touching route. The _feature handler correctly scopes _guard to just the store call so the 404 path remains distinct.
  • board_view.py: api() now parses defensively — a JSON error body throws its detail, a non-JSON body throws HTTP <status>. This catches both the new JSON 400 and any future non-JSON error.
  • tests/test_api.py: test_unusable_board_reads_surface_as_json_400_not_500 covers both GET routes with a BrokenStore raising BoardError, asserting 400 + message.

Observations

  • No issues found. The fix is minimal (3 files, ~36 lines), follows the established _guard pattern consistently, and the test covers the exact regression path described in the PR.
  • _feature's scoping (_guard on get_feature only, 404 outside) is correct — a BoardError becomes 400, a missing feature stays 404.

— Quinn, QA Engineer

@mabry1985 mabry1985 deleted the fix/board-errors-as-json branch July 2, 2026 08:38
@protoquinn

protoquinn Bot commented Jul 2, 2026

Copy link
Copy Markdown

Submitted APPROVE review on protoLabsAI/projectBoard-plugin#60.

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