janhq/jan · error · Error

llamacpp extension not available

Error message

llamacpp extension not available

What it means

Thrown by VectorDBExtension.embedTexts() when the llamacpp extension (resolved via getEmbeddingEngine / getByName) is missing or lacks an embed() method. This is the vector-db-extension's own embedding guard, mirroring rag-extension's error 66. All vector ingestion and search depends on it.

Source

Thrown at extensions/vector-db-extension/src/index.ts:249

    if (count <= budget || text.length <= MIN_CHUNK_SIZE_CHARS) return [text]
    const mid = Math.floor(text.length / 2)
    return [
      ...(await this.splitChunkToFit(text.slice(0, mid), budget, llm)),
      ...(await this.splitChunkToFit(text.slice(mid), budget, llm)),
    ]
  }

  private getEmbeddingEngine() {
    return window.core?.extensionManager.getByName('@janhq/llamacpp-extension') as AIEngine & {
      embed?: (texts: string[]) => Promise<{ data: Array<{ embedding: number[]; index: number }> }>
      getEmbeddingContextSize?: () => Promise<number | undefined>
      countEmbeddingTokens?: (texts: string[]) => Promise<number[]>
    }
  }

  private async embedTexts(texts: string[]): Promise<number[][]> {
    const llm = this.getEmbeddingEngine()
    if (!llm?.embed) throw new Error('llamacpp extension not available')

    const res = await llm.embed(texts)
    const data: Array<{ embedding: number[]; index: number }> = res?.data || []
    const out: number[][] = new Array(texts.length)
    for (const item of data) {
      out[item.index] = item.embedding
    }
    return out
  }

  async ingestFile(threadId: string, file: VectorDBFileInput, opts: VectorDBIngestOptions): Promise<AttachmentFileInfo> {
    // Check for duplicate file (same name + path)
    const existingFiles = await vecdb.listAttachments(this.collectionForThread(threadId)).catch(() => [])
    const duplicate = existingFiles.find((f: any) => f.name === file.name && f.path === file.path)
    if (duplicate) {
      throw new Error(`File '${file.name}' has already been attached to this thread`)
    }

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Enable and register @janhq/llamacpp-extension (verify getByName returns it).
  2. Load an embedding model so embed() is exposed.
  3. Update llamacpp-extension to a version implementing embed().
  4. Check the extension's startup log for a native dependency load failure.

Example fix

// before
await vecdbExt.ingestFile(threadId, file, opts)

// after
const llm = (window.core?.extensionManager.getByName('@janhq/llamacpp-extension') as any)
if (!llm?.embed) {
  throw new Error('Enable llamacpp-extension and load an embedding model')
}
await vecdbExt.ingestFile(threadId, file, opts)
Defensive patterns

Strategy: type-guard

Validate before calling

const llm = (window.core?.extensionManager.getByName('@janhq/llamacpp-extension') as any)
if (!llm?.embed) {
  // disable vector ingestion/search, prompt to enable extension + load embedding model
}

Type guard

function hasEmbed(llm: unknown): llm is { embed: (t: string[]) => Promise<any> } {
  return !!llm && typeof (llm as any).embed === 'function'
}

Prevention

When it happens

Trigger: Any ingestFile/ingestFileForProject/retrieval call when @janhq/llamacpp-extension is not loaded, crashed, or does not expose embed(); extension failed its native bind at startup.

Common situations: llamacpp-extension disabled while vector-db-extension is enabled; no embedding model configured; extension name refactored; native backend library missing prevented registration.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/1267c1eb313fdced. Report an issue: GitHub.