{"record":{"id":"0987afba97e72f6e","repo":"janhq/jan","slug":"not-a-supported-backend-archive-missing-llama-ser","errorCode":null,"errorMessage":"Not a supported backend archive! Missing llama-server binary.","messagePattern":"Not a supported backend archive! Missing llama-server binary\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"extensions/llamacpp-extension/src/index.ts","lineNumber":2904,"sourceCode":"      await invoke('decompress', { path: path, outputDir: backendDir })\n    } catch (e) {\n      logger.error(`Failed to install: ${String(e)}`)\n      throw new Error(`Failed to decompress archive: ${String(e)}`)\n    }\n\n    const serverName =\n      platformName === 'win' ? 'llama-server.exe' : 'llama-server'\n    const expectedBinDir = await joinPath([backendDir, 'build', 'bin'])\n    const expectedBinPath = await joinPath([expectedBinDir, serverName])\n\n    // Normalize varying archive layouts to `build/bin/`: Jan tarballs already\n    // ship it; upstream Linux tarballs nest under `llama-bXXXX/`; upstream\n    // Windows zips are flat with the binary + DLLs at the root.\n    if (!(await fs.existsSync(expectedBinPath))) {\n      const foundDir = await findLlamaServerDir(backendDir, serverName)\n      if (!foundDir) {\n        await fs.rm(backendDir)\n        throw new Error(\n          'Not a supported backend archive! Missing llama-server binary.'\n        )\n      }\n      if (foundDir !== expectedBinDir) {\n        const staging = `${backendDir}.staging`\n        try {\n          // Move the binary's dir into build/bin in one rename to keep relative\n          // symlinks intact (libggml.so → .so.0 → .so.0.10.0). A flat-root\n          // archive can't rename into its own subtree, so stage to a sibling.\n          if (foundDir === backendDir) {\n            await fs.mv(backendDir, staging)\n            await fs.mkdir(await joinPath([backendDir, 'build']))\n            await fs.mv(staging, expectedBinDir)\n          } else {\n            await fs.mkdir(await joinPath([backendDir, 'build']))\n            await fs.mv(foundDir, expectedBinDir)\n          }\n        } catch (e) {","sourceCodeStart":2886,"sourceCodeEnd":2922,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/llamacpp-extension/src/index.ts#L2886-L2922","documentation":"After decompression succeeds, the extension looks for the llama-server binary at the expected build/bin/ path. If not found there, findLlamaServerDir searches the extracted tree. If that search also returns null (no llama-server anywhere), the backend directory is removed and this error is thrown.","triggerScenarios":"The archive extracted successfully but contains no llama-server (or llama-server.exe on Windows) binary anywhere in its tree. The archive is either not a llama.cpp backend archive or is an incomplete/partial release.","commonSituations":"User installed a source-code archive instead of a binary release; the archive is a runtime-only package (e.g. CUDA DLLs) mistakenly passed to the backend installer; upstream release was published without the server binary.","solutions":["Use an archive that contains the llama-server binary (the binary release, not the source tarball).","If installing CUDA runtime DLLs, use installCudaRuntime instead of the backend installer.","Verify the archive contents manually (unzip/tar -tf) to confirm llama-server is present."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// After decompression, check for the binary before the extension does:\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nfunction findBinary(dir: string, serverName: string): string | null {\n  const entries = fs.readdirSync(dir, { withFileTypes: true })\n  for (const entry of entries) {\n    const full = path.join(dir, entry.name)\n    if (entry.isDirectory()) {\n      const found = findBinary(full, serverName)\n      if (found) return found\n    } else if (entry.name === serverName) {\n      return full\n    }\n  }\n  return null\n}\n\nconst found = findBinary(backendDir, serverName)\nif (!found) throw new Error('Archive has no llama-server; use a binary release')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only install binary-release archives, not source tarballs.","For CUDA runtime DLLs, use installCudaRuntime, not the backend installer.","Inspect archive contents (tar -tf / unzip -l) before installing to confirm llama-server is present."],"tags":["backend","validation","archive","missing-binary","llama-server","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}