Skip to content

claude-code-chat-browser: Distinct /api/search error codes and search UX polish #114

Closed

Description

@clean6378-max-it

Calendar Day

Tuesday, July 8, 2026

Planned Effort

Reduced from 5 to ~1–2 story points — most of the original 5 pt scope was shipped in Monday PR 2 (#121).

Depends on: Monday PR 1 (#120, feat/search-fts-index) and Monday PR 2 (#121, feat/search-errors-and-ux) merged to master.

Background — what Monday PRs already delivered

The original Tuesday spec (5 pt, item #2) called for error codes, API validation, search UI polish, docs, and tests. Monday PR 2 (#121, stacked on #120) shipped almost all of it:

Already done in PR #121

  • Error codes added to models/error_codes.py: SEARCH_EMPTY_QUERY, SEARCH_QUERY_TOO_LONG, SEARCH_INVALID_SINCE_DAYS, SEARCH_PROJECTS_UNAVAILABLE
  • api/search.py validation: empty q → 400, long q → 400, invalid since_days → 400, projects dir inaccessible → 503, unexpected errors → 500 with no exception leakage
  • Search UI (static/js/search.js): helper text (30-day window, result cap), "Search all history" checkbox (all_history=1), truncation warning, data-error-code on error paragraph, empty-result vs error-state distinction, snippet term highlighting via <mark> after esc()
  • docs/api-reference.md: error catalog extended, per-route Errors table for GET /api/search, query param docs for all_history and since_days
  • Tests: tests/test_search.py covers each failure mode (empty query, long query, invalid since_days, projects unavailable, index lock fallback, tokenless query fallback), tests/test_error_propagation.py no-leakage guard, tests/test_error_codes.py parametrized, Vitest tests for structured errors, truncation, and all-history

NOT done — residual for this ticket

Item Detail
SEARCH_INDEX_UNAVAILABLE error code Not added to ErrorCode enum — PR #121 handles index lock by falling back to live-scan or returning partial results, but never emits a named SEARCH_INDEX_UNAVAILABLE code
Explicit 503 SEARCH_INDEX_UNAVAILABLE response When the index is locked and live-scan also fails (or no partial results exist), the API should return 503 with this code instead of silently degrading
docs/api-reference.md entry for SEARCH_INDEX_UNAVAILABLE Missing from the catalog since the code doesn't exist yet
Test for SEARCH_INDEX_UNAVAILABLE 503 tests/test_search.py needs a case where index is locked AND live-scan is unavailable → 503

Scope

1. Add SEARCH_INDEX_UNAVAILABLE to models/error_codes.py

SEARCH_INDEX_UNAVAILABLE = "SEARCH_INDEX_UNAVAILABLE"

2. Wire 503 return in api/search.py

When _search_via_index detects index lock (index_locked flag) and has no partial results, and _search_live_scan also raises or returns no usable results, return:

error_response(ErrorCode.SEARCH_INDEX_UNAVAILABLE, "Search index is temporarily unavailable", 503)

PR #121 already detects index_locked in _search_via_index — this adds the explicit 503 code on the path where fallback also fails.

3. Document in docs/api-reference.md

Add row to error catalog and per-route Errors table:

code HTTP Routes Meaning
SEARCH_INDEX_UNAVAILABLE 503 GET /api/search FTS index is locked during rebuild and fallback is unavailable

4. Test coverage

  • tests/test_search.py: index locked + live-scan raises → 503 SEARCH_INDEX_UNAVAILABLE
  • tests/test_error_codes.py: add parametrized case

Acceptance Criteria

  • SEARCH_INDEX_UNAVAILABLE member in ErrorCode enum
  • Index locked + no fallback → 503 SEARCH_INDEX_UNAVAILABLE
  • docs/api-reference.md updated
  • tests/test_search.py covers the 503 path
  • mypy --strict, pytest, ruff, npm test pass
  • PR approved by at least 1 reviewer

Verification

cd C:\Users\Jasen\CppAliance\claude-code-chat-browser
.\.venv\Scripts\Activate.ps1
pytest tests/test_search.py tests/test_error_codes.py tests/test_error_propagation.py -q
pytest -q
mypy .
ruff check .

Out of scope

Everything below was in the original Tuesday spec but is now shipped by Monday PRs #120 + #121:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions