{"record":{"id":"37c21275df8e6774","repo":"janhq/jan","slug":"found-backendtype-backend-s-but-none-had-a-bui","errorCode":null,"errorMessage":"Found ${backendType} backend(s) but none had a build/bin directory to install into.","messagePattern":"Found (.+?) backend\\(s\\) but none had a build/bin directory to install into\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/llamacpp-extension/src/index.ts","lineNumber":2993,"sourceCode":"    if (targets.length === 0) {\n      throw new Error(\n        `No installed \"${backendType}\" backend found. Install that backend first, then add the CUDA runtime.`\n      )\n    }\n\n    let installed = 0\n    for (const t of targets) {\n      const binDir = await joinPath([\n        await getBackendDir(t.backend, t.version),\n        'build',\n        'bin',\n      ])\n      if (!(await fs.existsSync(binDir))) continue\n      await invoke('decompress', { path, outputDir: binDir })\n      installed++\n    }\n    if (installed === 0) {\n      throw new Error(\n        `Found ${backendType} backend(s) but none had a build/bin directory to install into.`\n      )\n    }\n    logger.info(\n      `CUDA runtime installed into ${installed} ${backendType} backend(s)`\n    )\n  }\n\n  /**\n   * Update a model with new information.\n   * @param modelId\n   * @param model\n   */\n  async update(modelId: string, model: Partial<modelInfo>): Promise<void> {\n    const modelFolderPath = await joinPath([\n      await this.getProviderPath(),\n      'models',\n      modelId,","sourceCodeStart":2975,"sourceCodeEnd":3011,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/llamacpp-extension/src/index.ts#L2975-L3011","documentation":"Thrown by installCudaRuntime after the loop over matching backends completes with installed===0. Each iteration computes getBackendDir(backend,version)/build/bin and skips (continue) if that directory does not exist on disk. So the backend is registered as installed but its actual build/bin folder is missing - the install record and the filesystem are out of sync.","triggerScenarios":"Backend install was interrupted (download cancelled mid-decompress) leaving a registry entry but no build/bin. The backend directory was moved or deleted by hand. A partial cleanup removed build/bin but left the backend manifest. Cross-drive install where getBackendDir resolves to a path that was never populated.","commonSituations":"User aborted a backend install mid-way then tried to add CUDA libs. Antivirus/quarantine deleted the .dll/.so files out of build/bin. Disk-full during decompress left the backend half-extracted. The models/backends directory was synced or copied between machines and the binary folder was excluded.","solutions":["Reinstall the backend cleanly (uninstall then installBackend) so build/bin is fully populated, then retry installCudaRuntime.","Check the resolved getBackendDir(backend,version) path on disk - if build/bin is absent or partial, remove the backend folder and reinstall.","Free disk space and disable AV exclusions for the data folder if binaries keep disappearing.","Confirm the backend manifest version matches the on-disk directory (a version bump may have left an orphan record)."],"exampleFix":"// before - registry says vulkan installed but build/bin is missing\nawait ext.installCudaRuntime('/d/cudart-llama-bin-vulkan.zip') // throws\n// after\nawait ext.uninstallBackend('vulkan', version)\nawait ext.installBackend('vulkan', version)\n// verify build/bin exists\nconst binDir = await joinPath([await getBackendDir('vulkan', version), 'build', 'bin'])\nif (!(await fs.existsSync(binDir))) throw new Error('reinstall failed')\nawait ext.installCudaRuntime('/d/cudart-llama-bin-vulkan.zip')","handlingStrategy":"validation","validationCode":"// Confirm each matching backend actually has build/bin on disk\nconst targets = (await getLocalInstalledBackends()).filter(b => b.backend === backendType)\nfor (const t of targets) {\n  const binDir = await joinPath([await getBackendDir(t.backend, t.version), 'build', 'bin'])\n  if (!(await fs.existsSync(binDir))) throw new Error(`backend ${t.backend}/${t.version} missing build/bin - reinstall it first`)\n}","typeGuard":"async function backendHasBinDir(b: { backend: string; version: string }): Promise<boolean> {\n  const binDir = await joinPath([await getBackendDir(b.backend, b.version), 'build', 'bin'])\n  return fs.existsSync(binDir)\n}","tryCatchPattern":"try { await ext.installCudaRuntime(path) }\ncatch (e) {\n  if (/none had a build\\/bin directory/.test(String(e))) { await ext.uninstallBackend(t, v); await ext.installBackend(t, v); await ext.installCudaRuntime(path) }\n  else throw e\n}","preventionTips":["Verify a backend install is complete (build/bin populated) before marking it installed.","Detect partial installs at startup and offer to repair them.","Don't expose the CUDA-runtime install action for backends whose build/bin is missing."],"tags":["cuda","backend","filesystem","corrupt-install","state-mismatch"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}