Skip to content

fix(web): surface /api/index errors in UI toast + result card#357

Merged
memtomem merged 1 commit intomainfrom
fix/web-index-surface-errors
Apr 21, 2026
Merged

fix(web): surface /api/index errors in UI toast + result card#357
memtomem merged 1 commit intomainfrom
fix/web-index-surface-errors

Conversation

@memtomem
Copy link
Copy Markdown
Owner

Summary

  • POST /api/index already returns IndexingStats.errors in the response body, but the Web UI's main-tab index button (app.js:2291) ignored the field and always fired a green "Indexed N chunks" toast. A base install without the [onnx] extra could index zero chunks, log hundreds of Embedding failed … fastembed is required lines to stderr, and still surface a clean success state in the UI.
  • Now the handler checks data.errors: on non-empty, it shows a red toast.index_partial toast (count + first error) and unhides an r-errors-row in the result card with up to 5 error lines and a "…and N more" trailer. Clean runs keep the original behavior.
  • i18n: new toast.index_partial and index.result.errors in en.json / ko.json.
  • Regression test: TestIndex::test_trigger_index_surfaces_engine_errors pins that the route writes the engine's error tuple through to the JSON body.

Fixes #354. Paired with #353 / #356 as the first-UX bundle for the upcoming v0.1.18.

Scope note

sources-memory-dirs.js (handleReindexOne, handleReindexAll) already gates on resp.errors — no changes needed there. Stream endpoint (/api/index/stream) is also outside this PR's scope; the user-visible path is the POST button.

Test plan

  • uv run pytest packages/memtomem/tests/test_web_routes.py::TestIndex (4 passed)
  • uv run pytest packages/memtomem/tests/test_i18n.py (12 passed — locale key parity)
  • uv run pytest -m "not ollama" (2036 passed, 0 regression)
  • uv run ruff check / format --check packages/memtomem

🤖 Generated with Claude Code

The backend route already propagates `IndexingStats.errors` into the
`IndexResponse` body, and the engine reports per-file embedding failures
via that tuple (see indexing/engine.py:519-532). But `app.js`'s index
button handler read only `data.indexed_chunks` and always showed a green
"Indexed N chunks" toast — so a run where every file failed to embed
(e.g. base install missing `fastembed`) looked like a clean success
even though `stderr` was flooded with `Embedding failed ... fastembed is
required` and `indexed_chunks=0`.

- Toggle toast type based on `data.errors`: `toast.index_partial` (red)
  when any error, existing `toast.indexed_count` (green) otherwise.
- Add a hidden `r-errors-row` in the result card that unhides with a red
  message column when `data.errors` is non-empty. Cap the visible list
  at 5 entries with a "…and N more" line — an ONNX-missing run can
  produce hundreds of identical errors.
- i18n: new `toast.index_partial` and `index.result.errors` in en + ko.
- Test: `TestIndex::test_trigger_index_surfaces_engine_errors` pins that
  the route writes the tuple through to the response JSON.

Sibling callers (`sources-memory-dirs.js` / `handleReindexAll`) already
gate on `resp.errors` — this PR only covers the main tab's index button.

Co-Authored-By: Claude <[email protected]>
@memtomem memtomem merged commit 13fd63a into main Apr 21, 2026
7 checks passed
@memtomem memtomem deleted the fix/web-index-surface-errors branch April 21, 2026 23:32
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

index: POST /api/index returns 200 OK when all embeddings fail

2 participants