tobi/qmd · error · Error

LLM operations are disabled in CI (set CI=true)

Error message

LLM operations are disabled in CI (set CI=true)

What it means

embedBatch() refuses to run when the LlamaCpp instance is in CI mode (_ciMode). CI mode disables all local LLM operations so that test/CI environments never attempt to load models or run inference.

Source

Thrown at src/llm.ts:1475

      const embedding = await context.getEmbeddingFor(safeText);

      return {
        embedding: Array.from(embedding.vector),
        model: options.model ?? this.embedModelUri,
      };
    } catch (error) {
      console.error("Embedding error:", error);
      return null;
    }
  }

  /**
   * Batch embed multiple texts efficiently
   * Uses Promise.all for parallel embedding - node-llama-cpp handles batching internally
   */
  async embedBatch(texts: string[], options: EmbedOptions = {}): Promise<(EmbeddingResult | null)[]> {
    if (this._ciMode) throw new Error("LLM operations are disabled in CI (set CI=true)");
    // Ping activity at start to keep models alive during this operation
    this.touchActivity();

    if (texts.length === 0) return [];

    try {
      const contexts = await this.ensureEmbedContexts();
      const n = contexts.length;

      if (n === 1) {
        // Single context: sequential (no point splitting)
        const context = contexts[0]!;
        const embeddings: ({ embedding: number[]; model: string } | null)[] = [];
        for (const text of texts) {
          try {
            const { text: safeText, truncated, limit } = await this.truncateToContextSize(text);
            if (truncated) {
              console.warn(`⚠ Batch text truncated to fit embedding context (${limit} tokens)`);

View on GitHub (pinned to dbfd0b4736)

Solutions

  1. Mock embedBatch in tests instead of calling the real one
  2. Set the env so CI mode is off (e.g. unset CI/NODE_ENV=test) if you genuinely need embeddings locally
  3. Use FTS-only search paths (qmd search) in CI

Example fix

// before
const embs = await llm.embedBatch(texts); // throws in CI
// after
const embs = llm.ciMode ? texts.map(() => null) : await llm.embedBatch(texts);
Defensive patterns

Strategy: try-catch

Validate before calling

if (llm.ciMode) return texts.map(() => null);

Type guard

const canEmbed = (l: LlamaCpp) => !l.ciMode;

Try / catch

try { await llm.embedBatch(texts); } catch (e) { if (/disabled in CI/.test((e as Error).message)) return texts.map(() => null); throw e; }

Prevention

When it happens

Trigger: Calling embedBatch(texts) while the process was constructed with CI mode enabled — e.g. NODE_ENV=test, CI=true env detection at construction time, or a test helper that instantiates LlamaCpp in CI mode.

Common situations: Running unit tests that accidentally call the real embedBatch; CI pipelines where model downloads/inference must be skipped; forgetting to unset CI mode in a local integration test that needs real embeddings.

Related errors


AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28). Data as JSON: /api/errors/29310b2c13e2e7ea. Report an issue: GitHub.