{"record":{"id":"11ab5ed75d4432a0","repo":"Mintplex-Labs/anything-llm","slug":"openrouter-failed-to-embed-error","errorCode":null,"errorMessage":"OpenRouter Failed to embed: ${error}","messagePattern":"OpenRouter Failed to embed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/EmbeddingEngines/openRouter/index.js","lineNumber":94,"sourceCode":"        .flat();\n      if (errors.length > 0) {\n        let uniqueErrors = new Set();\n        errors.map((error) =>\n          uniqueErrors.add(`[${error.type}]: ${error.message}`)\n        );\n\n        return {\n          data: [],\n          error: Array.from(uniqueErrors).join(\", \"),\n        };\n      }\n      return {\n        data: results.map((res) => res?.data || []).flat(),\n        error: null,\n      };\n    });\n\n    if (!!error) throw new Error(`OpenRouter Failed to embed: ${error}`);\n    return data.length > 0 &&\n      data.every((embd) => embd.hasOwnProperty(\"embedding\"))\n      ? data.map((embd) => embd.embedding)\n      : null;\n  }\n}\n\nasync function fetchOpenRouterEmbeddingModels() {\n  return await fetch(`https://openrouter.ai/api/v1/embeddings/models`, {\n    method: \"GET\",\n    headers: { \"Content-Type\": \"application/json\" },\n  })\n    .then((res) => res.json())\n    .then(({ data = [] }) => {\n      const models = {};\n      data.forEach((model) => {\n        models[model.id] = {\n          id: model.id,","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/EmbeddingEngines/openRouter/index.js#L76-L112","documentation":"Thrown at the end of OpenRouterEmbedder.embedChunks after all parallel embedding batches settle. Each batch runs as a self-catching Promise that resolves with {data:[], error} on failure instead of rejecting, so Promise.all never rejects. The collected unique errors are joined into one string and thrown here only if at least one batch failed. The wrapped error string is already formatted like '[429]: <message>' because the per-batch catch normalizes e.type and e.message from the OpenAI SDK response shape.","triggerScenarios":"Calling embedChunks/embedTextInput with an invalid or unset OPENROUTER_API_KEY, a non-existent EMBEDDING_MODEL_PREF, input text exceeding the 8191-token embeddingMaxChunkLength per chunk, OpenRouter HTTP rate limits (429), upstream provider outages, or network failures during the embeddings.create call. Because batches of up to maxConcurrentChunks (500) are fired in parallel, a single failing batch aborts the whole sequence.","commonSituations":"Switching embedding models without updating EMBEDDING_MODEL_PREF to a valid OpenRouter embedding model id; hitting OpenRouter free-tier rate limits when embedding a large workspace; passing oversized document chunks that exceed the model context window; API key rotated in the provider but not in the AnythingLLM env; transient OpenRouter routing errors to the backing model provider.","solutions":["Check the wrapped error string — the [type] prefix identifies the cause: [429] = rate limit (wait and retry / upgrade tier), [401] = bad key, [failed_to_embed] = network/model issue.","Verify OPENROUTER_API_KEY is set and valid by calling the OpenRouter embeddings models endpoint directly.","Confirm EMBEDDING_MODEL_PREF is a valid OpenRouter embedding model id (list via fetchOpenRouterEmbeddingModels).","For 429s, reduce workspace embed batch size or add delay/backoff; OpenRouter free tier has strict RPM limits.","Ensure no single input chunk exceeds 8191 tokens (the embeddingMaxChunkLength) — pre-split oversized chunks before embedding."],"exampleFix":"// before: oversized chunks cause model rejection\nawait openRouterEmbedder.embedChunks(hugeDocumentChunks);\n\n// after: pre-split chunks under the token limit before embedding\nconst MAX_TOKENS = 8000; // stay below 8191\nconst safeChunks = hugeDocumentChunks.flatMap(c => splitIfTooLong(c, MAX_TOKENS));\nawait openRouterEmbedder.embedChunks(safeChunks);","handlingStrategy":"try-catch","validationCode":"// Validate model and key before embedding\nconst { fetchOpenRouterEmbeddingModels } = require(\"./openRouter\");\nconst models = await fetchOpenRouterEmbeddingModels();\nif (!models[process.env.EMBEDDING_MODEL_PREF]) {\n  throw new Error(`Unknown OpenRouter embedding model: ${process.env.EMBEDDING_MODEL_PREF}`);\n}\nif (!process.env.OPENROUTER_API_KEY) {\n  throw new Error('OPENROUTER_API_KEY is not set');\n}","typeGuard":"/** @param {unknown} e */\nfunction isOpenRouterEmbedError(e) {\n  return e instanceof Error && /^OpenRouter Failed to embed:/.test(e.message);\n}","tryCatchPattern":"try {\n  const vectors = await embedder.embedChunks(chunks);\n  if (!vectors) throw new Error('Embedding produced no vectors');\n} catch (e) {\n  if (/\\[429\\]/.test(e.message)) { /* backoff and retry */ }\n  else if (/\\[401\\]|\\[403\\]/.test(e.message)) throw new Error('Bad OpenRouter API key');\n  else throw e;\n}","preventionTips":["Pre-validate EMBEDDING_MODEL_PREF against fetchOpenRouterEmbeddingModels before bulk embedding.","Keep chunks under the 8191-token embeddingMaxChunkLength by pre-splitting.","For large workspaces, throttle to avoid OpenRouter free-tier RPM limits.","Log the wrapped [type] prefix to classify failures for alerting."],"tags":["openrouter","embeddings","api-rate-limit","network","configuration"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}