Skip to content

fix(tasks-api): guard against HTML catch-all responses - #408

Closed
goforgin wants to merge 1 commit into
outsourc-e:mainfrom
goforgin:fix/tasks-api-probe-html-catchall
Closed

fix(tasks-api): guard against HTML catch-all responses#408
goforgin wants to merge 1 commit into
outsourc-e:mainfrom
goforgin:fix/tasks-api-probe-html-catchall

Conversation

@goforgin

@goforgin goforgin commented May 10, 2026

Copy link
Copy Markdown

Problem

After commit efcb7d14 renamed /api/hermes-tasks/api/claude-tasks, the task board showed "Failed to load tasks" in all columns despite the backend being healthy.

Root cause

probeBackend() in tasks-api.ts still probed the old /api/hermes-tasks route. Since the SPA catch-all returns 200 OK with an HTML body (not a 404), probeBackend() saw a successful response and didn't treat it as a dead route. Then resolveBackend() selected hermes-tasks as the winner (both counts were 0, and the old logic defaulted to hermes when equal), and the actual task fetch to that dead route threw — causing the board to fail entirely.

Fix

Two changes to src/lib/tasks-api.ts:

  1. probeBackend() — check Content-Type: application/json after a 200 response. Return -1 for non-JSON (HTML catch-all) instead of treating it as a valid empty backend.

  2. resolveBackend() — only prefer hermes-tasks when hermesCount > 0. When hermes is absent or returns non-JSON, default to claude-tasks (the active backend post-rename).

How to reproduce (before fix)

  1. Run hermes-workspace against a server that only has /api/claude-tasks (post-rename)
  2. Open the Tasks board
  3. All columns show "Failed to load tasks"

After fix

Tasks board loads correctly via /api/claude-tasks. If /api/hermes-tasks is ever restored and has data, it will still be preferred automatically.

The /api/hermes-tasks route was renamed to /api/claude-tasks in commit
efcb7d1, but the probe logic still listed the old route as a candidate.
When probed, the SPA catch-all returned a 200 HTML response instead of
a 404, so probeBackend() treated it as a valid (empty) backend and then
failed when the actual task fetch threw.

Fixes:
- probeBackend() now checks Content-Type: application/json and returns
  -1 for non-JSON responses, so future route renames degrade gracefully.
- resolveBackend() now only selects hermes if hermesCount > 0, defaulting
  to claude-tasks (the active backend post rename) when hermes is absent.
@outsourc-e

Copy link
Copy Markdown
Owner

Closing as superseded by #432. The validated fix was folded into the consolidated batch branch fix/issue-sweep-batch-20260514 for one review/merge path.

@outsourc-e outsourc-e closed this May 14, 2026
@outsourc-e outsourc-e mentioned this pull request May 14, 2026
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.

2 participants