Quick fix
For existing volumes / already-configured instances, one admin API call (same as UI: Settings → Retrieval → embedding):
# Replace url with your Ollama address; bare model name, no ollama/ prefix
curl -X POST http://localhost:3000/api/v1/retrieval/embedding/update \
-H "Authorization: Bearer <your-jwt>" -H 'Content-Type: application/json' \
-d '{"RAG_EMBEDDING_ENGINE":"ollama","RAG_EMBEDDING_MODEL":"nomic-embed-text","ollama_config":{"url":"http://host.docker.internal:11434","key":""}}'
Then delete the failed file and re-upload it (old files are not retried automatically).
Fresh container — set everything at first start (five vars):
docker run -d -p 3000:8080 --add-host host.docker.internal:host-gateway \
-v open-webui:/app/backend/data --name open-webui \
-e ENABLE_SIGNUP=true \
-e RAG_EMBEDDING_ENGINE=ollama \
-e RAG_EMBEDDING_MODEL=nomic-embed-text \
-e RAG_OLLAMA_BASE_URL=http://host.docker.internal:11434 \
-e OLLAMA_BASE_URLS=http://host.docker.internal:11434 \
ghcr.nju.edu.cn/open-webui/open-webui:main
What you will run into
You create a knowledge base in Open WebUI, upload a document, and the file stays failed:
Ollama embed error (404): model "nomic-embed-text" not found, try pulling it first
The model is pulled, Ollama is reachable (chat shows the models), but embedding just won't work. Tutorials tell you to set OLLAMA_BASE_URLS and RAG_EMBEDDING_MODEL; you set them all and it still 404s.
There are three layers of traps — miss any one and you get 404.
Why this happens
The embedding chain has three independent settings; any of them wrong → 404:
| Trap | Setting | Notes |
|---|---|---|
1. Model name with ollama/ prefix | RAG_EMBEDDING_MODEL | With the ollama engine the name must be bare (nomic-embed-text); ollama/nomic-embed-text is sent verbatim → model "ollama/nomic-embed-text" not found |
| 2. Embedding URL is a separate key | RAG_OLLAMA_BASE_URL (DB: rag.ollama.base_url) | Not OLLAMA_BASE_URLS (that only drives the model list/chat). When unset it falls back to the image default (measured: http://host.docker.internal:11434), which may not have the embedding model → 404 |
| 3. Config is persisted at first start; env stops working | DB config table | Settings are written to SQLite on first run; changing env vars and restarting afterwards has no effect (DB wins over env) — use the admin API |
Also note: default RELEVANCE_THRESHOLD=0 returns top-k even for unrelated queries — that does not mean retrieval is broken.
The embedding chain is "model name → embedding service address → storage config" in three serial hops; any broken hop shows up as "upload failed / retrieval 404".
The three mechanics: ① a model name prefixed with ollama/ is forwarded verbatim to ollama (the engine name is not a namespace), and ollama cannot find ollama/nomic-embed-text, so it 404s;
② the embedding service address is a separate config key RAG_OLLAMA_BASE_URL (DB rag.ollama.base_url), unrelated to the chat-facing OLLAMA_BASE_URLS — when unset it falls back to the image default (which may point at an instance without the embedding model);
③ config is persisted into the DB on first startup (SQLite config table), after which env vars no longer apply — DB wins over env, which is why "change env and restart" does nothing.
Deterministic takeaway: classify the scenario first — existing instance: update the DB config via the management API (/api/v1/retrieval/embedding/update); fresh container: pass everything at startup;
verify by uploading a file and watching vectorization succeed (seconds-level), not by staring at the config page;
with RELEVANCE_THRESHOLD=0, irrelevant queries returning top-k is normal, not a broken retriever.
Official troubleshooting reference (docs.openwebui.com/troubleshooting/rag/)
Directly relevant entries from the official RAG troubleshooting doc, side by side with this page's three-trap chain:
| Official entry | Relationship to this page |
|---|---|
400: 'NoneType' object has no attribute 'encode' | Sibling error: the embedding model is misconfigured / not fully downloaded / an external embedding service is unreachable, so Open WebUI can't generate vectors. Same root cause as "file failed + Ollama embed error (404)", different shape. Official fix: Admin -> Documents -> Embedding Model, save it again (forces a recheck/download) |
API upload then immediate KB add -> 400: The content provided is empty | Race condition: the upload endpoint returns a file_id immediately while extraction/embedding run in the background; adding to a KB before processing finishes sees empty content. Official fix: poll GET /api/v1/files/{file_id}/process/status until completed, then knowledge/<kb_id>/file/add |
ENABLE_KB_EXEC=True | For models with native function calling: gives the model a filesystem-style interface over the KB (ls/tree/grep/cat/read-by-line), more reliable than individual search tools. No effect in Legacy Mode |
| Reindex after changing the embedding model | Official and explicit: after switching models, Reindex all existing documents (Admin -> Documents), otherwise the new vectors don't take effect (same principle as trap 3 on this page: DB wins over env) |
| Embedding model selection | Single user getting started: all-MiniLM-L6-v2 (default, runs locally); multi-user with Ollama: nomic-embed-text via Ollama (offloads embeddings); production with API budget: text-embedding-3-small; air-gapped: nomic-embed-text or mxbai-embed-large via Ollama |
| 2048-token cap | Ollama default models often have only a 2048-token context, so even good retrieval only feeds in a slice. Official: for Ollama models raise the context length in Admin -> Models -> Advanced Params (8192+ for web search, 16384+ for complex pages); or enable Full Context Mode / Bypass Embedding |
RAG_SYSTEM_CONTEXT=True | Injects RAG context into the system message (fixed position) instead of the user message, so KV prefix caching works and follow-ups are nearly instant; enable when follow-up answers get slower and slower |
Correct API upload flow (official wait_for_processing pattern, avoids the empty-content race):
import requests, time
def wait_for_processing(token, file_id, timeout=300):
url = f'http://localhost:3000/api/v1/files/{file_id}/process/status"
headers = {"Authorization": f'Bearer {token}"}
start = time.time
while time.time - start < timeout:
r = requests.get(url, headers=headers).json
if r.get("status") == "completed":
return True
if r.get("status") == "failed":
raise RuntimeError(f'Processing failed: {r.get('error')}")
time.sleep(2) # poll every 2 seconds
raise TimeoutError("file processing timed out")
One observation consistent with this page's test: with RELEVANCE_THRESHOLD at its default 0, unrelated queries still return top-k results — retrieval isn't broken; raise the threshold to filter.
Step by step
1. Probe Ollama directly: model and naming — Diagnose (30s: model problem vs config problem)
# bare name (correct): 200 with embeddings
curl -s http://localhost:11434/api/embed -d '{"model":"nomic-embed-text","input":["test"]}' | head -c 200
# ollama/ prefix (wrong): 404 model "ollama/nomic-embed-text" not found
curl -s http://localhost:11434/api/embed -d '{"model":"ollama/nomic-embed-text","input":["test"]}'
Model missing: ollama pull nomic-embed-text (274MB; small models on the official registry are usually fine).
2. Read the exact failure of the file — Diagnose (read the error, layer by layer)
If the error is Ollama embed error (404) it's the three traps above; if it's Connection refused, that's the connectivity issue (see open-webui-ollama-connect).
3. Existing volume: use the admin API, not env — Required (config change; env won't work after first boot)
# Check the effective value (DB wins)
docker exec open-webui python3 -c "import sqlite3; con=sqlite3.connect('/app/backend/data/webui.db'); print(con.execute(\"SELECT key,value FROM config WHERE key='rag.ollama.base_url'\").fetchone)"
# Override via admin API (UI equivalent: Admin → Settings → Retrieval → embedding)
curl -X POST http://localhost:3000/api/v1/retrieval/embedding/update \
-H "Authorization: Bearer <token>" -H 'Content-Type: application/json' \
-d '{"RAG_EMBEDDING_ENGINE":"ollama","RAG_EMBEDDING_MODEL":"nomic-embed-text","ollama_config":{"url":"http://host.docker.internal:11434","key":""}}'
4. Delete the failed file and re-upload — Required (old files don't retry)
Upload → wait for status completed (seconds). Still failed? Read the error text and walk the layers.
5. Create KB → add file → query — Required (acceptance)
# create knowledge base → kb_id
curl -X POST http://localhost:3000/api/v1/knowledge/create -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' -d '{"name":"kb"}'
# add file (file_id from the upload response)
curl -X POST http://localhost:3000/api/v1/knowledge/<kb_id>/file/add -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' -d '{"file_id":"<file_id>"}'
# query
curl -X POST http://localhost:3000/api/v1/retrieval/query/collection -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' -d '{"collection_names":["<kb_id>"],"query":"a keyword from the doc","k":3}'
How to confirm it works
- The uploaded file is
completed(not failed); logs showembeddings generated ... added ... to collection. - The query hits the document content and the metadata
embedding_configis correct:{'engine': 'ollama', 'model': 'nomic-embed-text'}. - Direct
POST /api/embedwith the bare name returns 200 (768-dim vector); the prefixed name returning 404 is expected. - Note: unrelated queries returning results ≠ broken (default threshold 0 returns top-k); raise
RELEVANCE_THRESHOLDin settings if you want filtering.
Other environments
| Environment | Notes | |||
|---|---|---|---|---|
| Older Open WebUI | Embedding lives in Admin → Retrieval settings; same three spots (engine / model name / URL); don't point it at the model-list OLLAMA_BASE_URLS | |||
| OpenAI-compatible embedding | Engine = openai; set openai_config base_url + key; model name is the provider's (e.g. text-embedding-3-small) | |||
| Docker Desktop / Linux | host.docker.internal needs --add-host host.docker.internal:host-gateway on Linux; Docker Desktop supports it out of the box | |||
| Chat-layer auto retrieval | Depends on the model's tool-calling: a 0.5B model was measured NOT triggering retrieval (tool-side evidence); use ≥7B tool-calling models or inject knowledge into the prompt | |||
| Reused/upgraded old volume | Old persisted config wins over new env — use the admin API or edit the DB directly | |||
| Bind-mounted data dir (fresh deploy) | A bind-mount may mask bundled embedding models (open-webui#29014, external report, not reproduced locally); after mounting, confirm the Embedding Model list still has a usable model | Reused/upgraded old volume | Old persisted config wins over new env — use the admin API or edit the DB directly |
Symptom
- Knowledge-base files stuck at
failed, error containsOllama embed error (404): model "nomic-embed-text" not found, try pulling it first; - The model list shows the embedding model and chat works, but KB retrieval doesn't;
- Set
OLLAMA_BASE_URLS/RAG_EMBEDDING_MODELper tutorials, restarted, still 404.
Cause
- Model name written with an
ollama/prefix (404); - The embedding URL is a separate setting
RAG_OLLAMA_BASE_URL, which falls back to a default instance (possibly without the model); - After first start the config is persisted in SQLite and DB wins over env; env changes are ignored.
Solution
- Probe
POST /api/embed: bare name 200 / prefixed 404; 2.ollama pullthe embedding model; 3. Existing volumes: admin APIPOST /api/v1/retrieval/embedding/updatewithollama_config.url(env won't work); 4. Delete failed files and re-upload, wait forcompleted; 5. Create KB + add file + query to verify; 6. If unrelated queries return top-k, raise RELEVANCE_THRESHOLD.
Verification Evidence
- Local reproduction (2026-08-30, isolated containers 3004/11435; tool-side containers and the system snap ollama untouched):
- Direct
/api/embed: barenomic-embed-text→ 200 (768 dims, L2 norm 1.0);ollama/nomic-embed-text→ 404model "ollama/nomic-embed-text" not found; - First start without
RAG_OLLAMA_BASE_URL→ upload failed, errorOllama embed error (404)...; DBrag.ollama.base_urlpersisted as defaulthost.docker.internal:11434; - Restart with
RAG_OLLAMA_BASE_URL=...11435env → still 404 (DB wins over env — full mechanism of trap 2); - Admin API
POST /api/v1/retrieval/embedding/updatewithollama_config.url→ DB shows 11435; - Re-upload →
completedin ~2s; create KB + add file → 200; query for the default admin port → hits=1 with the correct content chunk (the KB entry stating that the default admin port is 8123) and metaembedding_config: {'engine': 'ollama', 'model': 'nomic-embed-text'}; - An unrelated Chinese-language query also returned 1 hit → default threshold 0 returns top-k;
- Test containers and volumes cleaned up.
- Chat-layer auto retrieval limitation: tool-side evidence (local repro log 2026-08-30): a 0.5B model does not trigger tool calls and hallucinates; the retrieval layer itself works.
local repro log 2026-08-30
Related canonicals
Read in order: precondition -> same root / same domain / related:
- Same root:
- Forgot the admin password / can't log in (same root: webui.db is the single source of truth (config table and auth table both beat env/signup))
- Related (similar errors, different cause):
- Open WebUI shows "cannot connect to Ollama" (Connection refused cases; host.docker.internal and OLLAMA_BASE_URLS)
- ollama pull stuck/timeout (slow embedding model downloads)
- Move the model directory (embedding models move with the directory)
References
- Open WebUI official RAG troubleshooting — <https://docs.openwebui.com/troubleshooting/rag/>
Applicable tools (2)
This problem is linked from the tool pages below — reachable from either side.
open-webuiollamaSource & evidence
← Local LLM domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk