{"record":{"id":"c4fefaea93306e88","repo":"Mintplex-Labs/anything-llm","slug":"ollama-returned-empty-embeddings-for-batch","errorCode":null,"errorMessage":"Ollama returned empty embeddings for batch!","messagePattern":"Ollama returned empty embeddings for batch!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/EmbeddingEngines/ollama/index.js","lineNumber":115,"sourceCode":"    for (let i = 0; i < textChunks.length; i += this.maxConcurrentChunks) {\n      const batch = textChunks.slice(i, i + this.maxConcurrentChunks);\n      currentBatch++;\n\n      try {\n        // Use input param instead of prompt param to support batch processing\n        const res = await this.client.embed({\n          model: this.model,\n          input: batch,\n          options: {\n            // Always set the num_ctx to the max chunk length defined by the user in the settings\n            // so that the maximum context window is used and content is not truncated.\n            num_ctx: this.embeddingMaxChunkLength,\n          },\n        });\n\n        const { embeddings } = res;\n        if (!Array.isArray(embeddings) || embeddings.length === 0)\n          throw new Error(\"Ollama returned empty embeddings for batch!\");\n\n        // Using prompt param in embed() would return a single embedding (number[])\n        // but input param returns an array of embeddings (number[][]) for batch processing.\n        // This is why we spread the embeddings array into the data array.\n        data.push(...embeddings);\n        reportEmbeddingProgress(data.length, textChunks.length);\n        this.log(\n          `Batch ${currentBatch}/${totalBatches}: Embedded ${embeddings.length} chunks. Total: ${data.length}/${textChunks.length}`\n        );\n      } catch (err) {\n        this.log(err.message);\n        error = err.message;\n        data = [];\n        break;\n      }\n    }\n\n    if (!!error) throw new Error(`Ollama Failed to embed: ${error}`);","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/utils/EmbeddingEngines/ollama/index.js#L97-L133","documentation":"Ollama answered the /api/embed call with HTTP 200, but the response's `embeddings` field was missing or an empty array. Because the code sends the batch via the `input` parameter, it expects exactly one embedding per input string; zero results means the model ran but produced nothing. The most common cause is that the configured model is a generative/LLM model with no embedding capability, or the Ollama version is too old to return the batch `embeddings` shape.","triggerScenarios":"EMBEDDING_MODEL_PREF points at a chat model (llama3, mistral, qwen) instead of an embedding model; a model-name/tag mismatch so Ollama resolves a different model; an Ollama version that predates the /api/embed batch endpoint's response shape; a server returning an error-shaped body with status 200.","commonSituations":"Reusing the same model name for the LLM and the embedder in settings; forgetting `ollama pull nomic-embed-text` on a new machine; very old Ollama installs on NAS devices or routers.","solutions":["Point EMBEDDING_MODEL_PREF at a real embedding model (nomic-embed-text, mxbai-embed-large, all-minilm, snowflake-arctic-embed) and `ollama pull` it.","Match the model name from `ollama list` exactly, including the tag.","Upgrade Ollama to a recent release so /api/embed with `input` arrays returns `embeddings`.","Reproduce outside AnythingLLM: `curl http://localhost:11434/api/embed -d '{\"model\":\"nomic-embed-text\",\"input\":[\"hi\"]}'` and confirm embeddings is non-empty."],"exampleFix":"# .env — before (llama3 is a chat model and cannot embed)\nEMBEDDING_MODEL_PREF=llama3\n\n# .env — after\nEMBEDDING_MODEL_PREF=nomic-embed-text","handlingStrategy":"try-catch","validationCode":"async function modelProducesEmbeddings(basePath, model) {\n  const res = await fetch(`${basePath}/api/embed`, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({ model, input: [\"ping\"] }),\n  });\n  const body = await res.json();\n  return Array.isArray(body.embeddings) && body.embeddings.length > 0;\n}\nif (!(await modelProducesEmbeddings(basePath, model))) {\n  throw new Error(`${model} is not an embedding model — pick one from \\`ollama list\\` that embeds.`);\n}","typeGuard":"function hasEmbeddings(payload) {\n  return (\n    payload !== null &&\n    typeof payload === \"object\" &&\n    Array.isArray(payload.embeddings) &&\n    payload.embeddings.length > 0 &&\n    payload.embeddings.every((e) => Array.isArray(e))\n  );\n}","tryCatchPattern":"try {\n  const vectors = await embedder.embedChunks(chunks);\n} catch (err) {\n  if (err.message.includes(\"empty embeddings\")) {\n    // model is not an embedding model: fix EMBEDDING_MODEL_PREF, do not retry\n  } else {\n    throw err;\n  }\n}","preventionTips":["Validate the embedder model with a one-string smoke test when saving settings.","Pull embedding models explicitly (ollama pull nomic-embed-text) rather than relying on auto-pull of chat tags.","Keep model ids in config exactly as shown by ollama list."],"tags":["ollama","embeddings","empty-response","model-selection"],"backgroundTag":"empty-api-response","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}