project-nomad/admin/app/services
Chris Sherwood c2fb809c81 fix(ai): a failed Ollama model pull is reported to the user as a success
Ollama's /api/pull returns HTTP 200 and reports failures IN-BAND, as a JSON
line inside the NDJSON stream body:

    HTTP_STATUS=200
    {"status":"pulling manifest"}
    {"error":"pull model manifest: file does not exist"}

The stream handler only ever read completed/total/digest off each line and
silently dropped everything else, including that error line. The stream then
ended normally, on('end') resolved unconditionally, and we logged the model as
downloaded successfully. on('error') never fires for this, because at the HTTP
layer the request succeeded.

Every failed model pull, for any reason, was reported as a success. On #1071
that surfaced as an ~800 GB fp16 model "downloading" in two seconds and nothing
being installed, which had been triaged twice as disk space or a stale blob.
Those explanations produce workarounds that cannot work, since the pull never
reaches the disk at all.

Three changes:

- Check parsed.error in the data handler and destroy the stream with it, so the
  existing catch reports a real failure.
- Verify the model is actually in getModels() before returning success. This is
  the load-bearing half: it catches silent failures we have not anticipated,
  not only the ones Ollama labels. includeEmbeddings must be true or
  nomic-embed-text fails verification after a good pull, and names are
  normalised because Ollama resolves a bare name to ":latest".
- Treat an in-band "model does not exist" as permanent. It was retryable, so a
  bad model name spun through attempts: 10 on exponential backoff and the user
  watched a delayed job for hours instead of being told the name was wrong.

Verified on NOMAD3 against the shipped v1.34.0 build, which carries the same
defect:

- bogus tag, before: 'Model "..." downloaded successfully.'
- bogus tag, after:  'Failed to download model "...": pull model manifest:
  file does not exist', and the job stops at 1 attempt instead of retrying
- real model (qwen2.5:0.5b): still succeeds, passes verification, and is
  present in `ollama list`

Fixes #1273
Refs #1071

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtGWCVMPYn6qPWVYiycK74
2026-09-29 15:54:41 -07:00
..
app_auto_update_service.ts feat(supply-depot): opt-in automatic updates for installed apps 2026-06-23 04:46:52 +00:00
auto_update_service.ts feat(supply-depot): opt-in automatic updates for installed apps 2026-06-23 04:46:52 +00:00
benchmark_service.ts fix(benchmark): don't submit unresolved PCI ids as the GPU model (#1165) 2026-08-04 03:39:58 +00:00
benchmark_telemetry.ts feat(benchmark): end-of-run score reveal + NVIDIA GPU-util overlay (#1087) 2026-08-04 03:37:40 +00:00
chat_service.ts fix(AI): tell a broken grammar apart from a backend that never had one 2026-09-29 15:54:41 -07:00
collection_manifest_service.ts feat: support gated downloads for self-hosted curated content (#1172) 2026-08-04 03:39:55 +00:00
collection_update_service.ts fix(downloads): let interrupted content downloads resume (#1202) 2026-08-04 03:40:01 +00:00
condition_service.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-08-04 03:38:33 +00:00
container_registry_service.ts fix(updates): resolve relative registry pagination URL so tag listing doesn't crash (#945) 2026-06-23 04:46:59 +00:00
content_auto_update_service.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-08-04 03:38:33 +00:00
context_window_service.ts feat(AI): budget the prompt and actually set the context window (#1253) 2026-09-29 15:54:41 -07:00
countries_service.ts feat(Maps): regional map downloads via go-pmtiles extract (#780) 2026-05-20 10:16:00 -07:00
creator_pack_service.ts fix(downloads): let interrupted content downloads resume (#1202) 2026-08-04 03:40:01 +00:00
custom_app_guard.ts feat: supply depot 2026-06-23 04:46:45 +00:00
docker_service.ts feat(AI): budget the prompt and actually set the context window (#1253) 2026-09-29 15:54:41 -07:00
docs_service.ts docs: add an in-app Drug Reference guide (#1161) 2026-08-04 03:39:58 +00:00
download_service.ts fix(queue): clear terminal jobs before re-dispatch so downloads aren't silently dropped 2026-09-29 15:54:41 -07:00
drug_reference_service.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-08-04 03:38:33 +00:00
eval_corpus_service.ts feat(AI): budget the prompt and actually set the context window (#1253) 2026-09-29 15:54:41 -07:00
eval_generation_service.ts feat(AI): let retrieval decline instead of making the prompt paper over it 2026-09-29 15:54:41 -07:00
eval_report_service.ts feat(AI): budget the prompt and actually set the context window (#1253) 2026-09-29 15:54:41 -07:00
eval_retrieval_service.ts feat(AI): let retrieval decline instead of making the prompt paper over it 2026-09-29 15:54:41 -07:00
kiwix_catalog_service.ts fix(zim): extract Kiwix catalog URL into system-wide constant 2026-09-02 09:40:38 -07:00
kiwix_library_service.ts fix(kiwix): self-heal a missing or corrupt library XML on startup 2026-06-23 04:46:56 +00:00
map_service.ts fix(maps): warn when world basemap missing instead of silent grey map (#1104) 2026-08-04 03:38:29 +00:00
nomad_md_service.ts feat(AI): nomad.md for custom instructions (#1127) 2026-08-04 03:38:33 +00:00
ollama_service.ts fix(ai): a failed Ollama model pull is reported to the user as a success 2026-09-29 15:54:41 -07:00
queue_service.ts fix(queue): share one ioredis connection across BullMQ queues and workers (#1009) 2026-06-23 04:47:08 +00:00
rag_pipeline_service.ts feat(AI): let retrieval decline instead of making the prompt paper over it 2026-09-29 15:54:41 -07:00
rag_service.ts fix(rag): don't abandon a ZIM after one sparse batch 2026-09-29 15:54:41 -07:00
system_service.ts feat(AI): let retrieval decline instead of making the prompt paper over it 2026-09-29 15:54:41 -07:00
system_update_service.ts feat(system): add opt-in automatic updates for the core NOMAD app 2026-06-23 04:46:51 +00:00
token_calibration_service.ts feat(AI): budget the prompt and actually set the context window (#1253) 2026-09-29 15:54:41 -07:00
zim_extraction_service.ts fix(rag): don't abandon a ZIM after one sparse batch 2026-09-29 15:54:41 -07:00
zim_service.ts fix(zim): extract Kiwix catalog URL into system-wide constant 2026-09-02 09:40:38 -07:00