Mintplex-Labs/anything-llm · error · Error

OpenAI Failed to embed: ${error}

Error message

OpenAI Failed to embed: ${error}

What it means

Thrown at the end of embedChunks after Promise.all when any concurrent batch to OpenAI failed. Batches of maxConcurrentChunks (500) are sent via embeddings.create; each rejection is caught and resolved as {data:[],error:e}, errors are deduplicated into [type]: message, and any error aborts the whole sequence to avoid gaps in the vector data. This is the canonical batched-embed failure path shared with the LiteLLM/LocalAI embedders.

Source

Thrown at server/utils/EmbeddingEngines/openAi/index.js:92

        .flat();
      if (errors.length > 0) {
        let uniqueErrors = new Set();
        errors.map((error) =>
          uniqueErrors.add(`[${error.type}]: ${error.message}`)
        );

        return {
          data: [],
          error: Array.from(uniqueErrors).join(", "),
        };
      }
      return {
        data: results.map((res) => res?.data || []).flat(),
        error: null,
      };
    });

    if (!!error) throw new Error(`OpenAI Failed to embed: ${error}`);
    return data.length > 0 &&
      data.every((embd) => embd.hasOwnProperty("embedding"))
      ? data.map((embd) => embd.embedding)
      : null;
  }
}

module.exports = {
  OpenAiEmbedder,
};

View on GitHub (pinned to 526360e320)

Solutions

  1. Decode the joined [type]: message — 401 -> fix OPEN_AI_KEY; 429 -> reduce batch size / add backoff / raise TPM limit; 404 -> switch EMBEDDING_MODEL_PREF to a current model (text-embedding-3-small/large)
  2. Ensure document chunks are within the model's context (8191 tokens for ada-002; larger for v3)
  3. Add bounded retry with exponential backoff in the caller for 429/5xx
  4. Check status.openai.com for ongoing incidents

Example fix

// before
EMBEDDING_MODEL_PREF=text-embedding-ada-002  // hits 429/404 depending on account

// after
EMBEDDING_MODEL_PREF=text-embedding-3-small
Defensive patterns

Strategy: retry

Validate before calling

// confirm model + a working call before a large ingest
async function openAiEmbeds(openai, model, sample = 'hello') {
  const r = await openai.embeddings.create({ model, input: sample });
  return Array.isArray(r.data?.[0]?.embedding);
}

Type guard

function isOpenAiEmbedError(e) {
  return e instanceof Error && /OpenAI Failed to embed/.test(e.message);
}

Try / catch

async function embedWithRetry(embedder, chunks, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try { return await embedder.embedChunks(chunks); }
    catch (e) {
      const transient = /429|5\d\d|ETIMEDOUT|Failed to fetch/.test(e.message);
      if (!transient || i === attempts - 1) throw e;
      await new Promise(r => setTimeout(r, 2 ** i * 1000));
    }
  }
}

Prevention

When it happens

Trigger: One or more batched /v1/embeddings calls rejecting: 401 bad/expired key; 429 rate limit / quota exhausted; 404 unknown model (e.g. EMBEDDING_MODEL_PREF set to a deprecated id); 400 input too long for the model's token limit; 5xx OpenAI outage; batch exceeding 8191 token embeddingMaxChunkLength for ada-002.

Common situations: Quota/billing exhaustion; deprecated model id (text-embedding-ada-002 replaced by v3); chunk size larger than the model's context; concurrent jobs spiking past the tokens-per-minute limit; org-level rate limits; transient api.openai.com 5xx.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/cd95fcd1992643e0. Report an issue: GitHub.