{"record":{"id":"0fb00f4e0fbf7617","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"local-embedding-model-is-still-loading-download-i","errorCode":null,"errorMessage":"Local embedding model is still loading (download/initialization in progress). Please try again later.","messagePattern":"Local embedding model is still loading \\(download/initialization in progress\\)\\. Please try again later\\.","errorType":"exception","errorClass":"EmbeddingNotReadyError","httpStatus":null,"severity":"warning","filePath":"MemoryCore/src/core/store/embedding.ts","lineNumber":290,"sourceCode":"      this.logger?.info(`${TAG} Local embedding resources released`);\n    }\n  }\n\n  /**\n   * Assert the model is ready. Throws EmbeddingNotReadyError if not.\n   */\n  private assertReady(): void {\n    if (this.initState === \"ready\" && this.embeddingContext) {\n      return;\n    }\n    if (this.initState === \"failed\") {\n      throw new EmbeddingNotReadyError(\n        `Local embedding model initialization failed: ${this.initError?.message ?? \"unknown error\"}. ` +\n        `Call startWarmup() to retry.`,\n      );\n    }\n    if (this.initState === \"initializing\") {\n      throw new EmbeddingNotReadyError(\n        \"Local embedding model is still loading (download/initialization in progress). Please try again later.\",\n      );\n    }\n    // \"idle\" — startWarmup() was never called\n    throw new EmbeddingNotReadyError(\n      \"Local embedding model warmup has not been started. Call startWarmup() first.\",\n    );\n  }\n\n  /**\n   * Truncate input text to stay within the model's context window.\n   * embeddinggemma-300m has a 256-token limit; we use a character-based\n   * heuristic (LOCAL_MAX_INPUT_CHARS) as a safe proxy.\n   */\n  private truncateInput(text: string): string {\n    if (text.length <= LOCAL_MAX_INPUT_CHARS) return text;\n    this.logger?.debug?.(\n      `${TAG} Input truncated from ${text.length} to ${LOCAL_MAX_INPUT_CHARS} chars (model context limit)`,","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/core/store/embedding.ts#L272-L308","documentation":"assertReady() throws EmbeddingNotReadyError when initState is 'initializing', meaning startWarmup() has been called but the model is still downloading/initializing. The embedder deliberately does not queue or block: embed()/embedBatch() fail fast so the caller can retry later or fall back. The context is not yet set, so serving requests now would be impossible.","triggerScenarios":"Calling embed() or embedBatch() concurrently with an in-flight startWarmup() — e.g. the first request after server boot while the GGUF model is still downloading, or right after close()+startWarmup() with a large model still loading.","commonSituations":"Cold-start race: traffic arrives before the model finishes its first download/load (slow network, multi-GB GGUF); tests that don't await warmup before calling embed; load balancer sending traffic to a just-started instance.","solutions":["Retry the embed call after a delay until initState becomes 'ready' (poll or exponential backoff).","Await the warmup promise before issuing embed calls, e.g. expose/track startWarmup()'s returned promise and gate requests on it.","Add a readiness gate (health check / lazy init in a request queue) so requests wait for model readiness instead of failing.","Fall back to a remote embedding API during local model warmup."],"exampleFix":"// before\nawait embedder.startWarmup();\nembedder.embed(text); // not awaited; may hit 'still loading'\n// after\nawait embedder.startWarmup(); // wait until model is ready\nconst vec = await embedder.embed(text);","handlingStrategy":"retry","validationCode":"if ((embedder as any).initState === \"initializing\") {\n  await waitForReady(embedder); // poll/backoff until initState === \"ready\"\n}","typeGuard":"function isEmbeddingNotReadyError(e: unknown): e is EmbeddingNotReadyError {\n  return e instanceof EmbeddingNotReadyError;\n}","tryCatchPattern":"async function embedWithRetry(embedder, text, tries = 10) {\n  for (let i = 0; i < tries; i++) {\n    try {\n      return await embedder.embed(text);\n    } catch (e) {\n      if (isEmbeddingNotReadyError(e) && /still loading/.test(e.message)) {\n        await new Promise(r => setTimeout(r, 500 * (i + 1)));\n        continue;\n      }\n      throw e;\n    }\n  }\n  throw new Error(\"embedding model did not become ready in time\");\n}","preventionTips":["Gate request handling on warmup completion (health-check readiness or awaited startWarmup promise).","Never fire embed calls concurrently with startWarmup in startup code; await it.","Warm up the model before the load balancer marks the instance healthy.","Use exponential backoff with a cap when retrying while-loading errors."],"tags":["embedding","not-ready","async","cold-start","retry"],"backgroundTag":"embedding-model-not-ready","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}