chroma-core/chroma · error · Error

Error calling Cloudflare Workers AI API: ${error.message}

Error message

Error calling Cloudflare Workers AI API: ${error.message}

What it means

The catch-all wrapper in CloudflareWorkersAIEmbeddingFunction.generate: any Error thrown in the try block - fetch network failures (DNS, ECONNREFUSED, timeouts), response.json() parse failures on non-JSON bodies (HTML error pages), and the inner 'resp.detail || Unknown error' throw - is re-thrown as 'Error calling Cloudflare Workers AI API: <original.message>'. This is the error you actually see in stack traces from this embedding function; the original cause is preserved only inside the message text, not as error.cause.

Source

Thrown at clients/js/packages/chromadb-core/src/embeddings/CloudflareWorkersAIEmbeddingFunction.ts:85

        text: texts,
      };

      const response = await fetch(this.api_url, {
        method: "POST",
        headers: this.headers,
        body: JSON.stringify(payload),
      });

      const resp = await response.json();

      if (!resp.result || !resp.result.data) {
        throw new Error(resp.detail || "Unknown error");
      }

      return resp.result.data;
    } catch (error) {
      if (error instanceof Error) {
        throw new Error(
          `Error calling Cloudflare Workers AI API: ${error.message}`,
        );
      } else {
        throw new Error(`Error calling Cloudflare Workers AI API: ${error}`);
      }
    }
  }

  buildFromConfig(config: StoredConfig): CloudflareWorkersAIEmbeddingFunction {
    return new CloudflareWorkersAIEmbeddingFunction({
      model_name: config.model_name,
      account_id: config.account_id,
      api_key_env_var: config.api_key_env_var,
      gateway_id: config.gateway_id ?? undefined,
    });
  }

  getConfig(): StoredConfig {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Read the suffix after 'Error calling Cloudflare Workers AI API:' - 'fetch failed' means network, a JSON SyntaxError means a non-JSON error page, other text is the API's detail.
  2. For transient network issues, retry with backoff around generate().
  3. Verify egress to api.cloudflare.com (curl) and proxy env vars (HTTPS_PROXY) in the failing environment.
  4. If the suffix is 'Unknown error' or a Cloudflare detail, debug per the API-error case (model/account/key).

Example fix

// before
const embs = await ef.generate(texts); // opaque wrapped failure

// after
async function embedWithRetry(texts: string[], attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await ef.generate(texts);
    } catch (e) {
      const msg = (e as Error).message;
      if (i === attempts - 1 || !msg.includes('fetch failed')) throw e;
      await new Promise((r) => setTimeout(r, 2 ** i * 500));
    }
  }
  throw new Error('unreachable');
}
Defensive patterns

Strategy: retry

Try / catch

async function generateWithRetry(texts: string[], tries = 3) {
  let lastErr: unknown;
  for (let i = 0; i < tries; i++) {
    try {
      return await ef.generate(texts);
    } catch (e) {
      lastErr = e;
      const msg = (e as Error).message ?? '';
      const transient =
        msg.includes('fetch failed') || msg.includes('ETIMEDOUT') || msg.includes('ECONNRESET');
      if (!transient || i === tries - 1) break;
      await new Promise((r) => setTimeout(r, 2 ** i * 500));
    }
  }
  throw lastErr;
}

Prevention

When it happens

Trigger: await ef.generate(texts) while offline/DNS-blocked; corporate proxy rejecting api.cloudflare.com; 502/52x returning HTML so response.json() throws SyntaxError; the inner Unknown error throw being re-wrapped (double-wrapping).

Common situations: CI without external network egress; firewall/proxy whitelisting gaps; transient Cloudflare gateway incidents; response body unexpectedly HTML (auth wall, captive portal).

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/11589575c1724cba. Report an issue: GitHub.