{"record":{"id":"a522f83ce955626c","repo":"janhq/jan","slug":"extension-does-not-support-backend-installation","errorCode":null,"errorMessage":"Extension does not support backend installation","messagePattern":"Extension does not support backend installation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/hooks/useBackendUpdater.ts","lineNumber":429,"sourceCode":"\n      if (!llamacppExtension) {\n        // Try to find by type or other properties\n        const possibleExtension = allExtensions.find(\n          (ext) =>\n            ext.constructor.name.toLowerCase().includes('llamacpp') ||\n            (ext.type &&\n              ext.type()?.toString().toLowerCase().includes('inference'))\n        )\n\n        if (!possibleExtension) {\n          throw new Error('LlamaCpp extension not found')\n        }\n\n        extensionToUse = possibleExtension\n      }\n\n      if (!extensionToUse || !('installBackend' in extensionToUse)) {\n        throw new Error('Extension does not support backend installation')\n      }\n\n      // Call the extension's installBackend method\n      const extension = extensionToUse as LlamacppExtension\n      await extension.installBackend?.(filePath)\n\n      // Refresh backend list to update UI. Prefer the narrow\n      // refreshBackendOptions (just rewrites the dropdown options); fall\n      // back to the heavy configureBackends path for older extensions.\n      if (extension.refreshBackendOptions) {\n        await extension.refreshBackendOptions()\n      } else {\n        await extension.configureBackends?.()\n      }\n    } catch (error) {\n      console.error('Error installing backend:', error)\n      throw error\n    }","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/hooks/useBackendUpdater.ts#L411-L447","documentation":"Thrown when an extension was found for backend installation but it lacks the `installBackend` method. Capability gate via `'installBackend' in extension`. Means the matched extension is wrong (shadow) or is an older llamacpp version without manual-install support.","triggerScenarios":"Fuzzy matcher picked a non-llamacpp inference extension, or the installed llamacpp extension predates the `installBackend` API. Same shape as error 129 but for the install capability.","commonSituations":"Old extension version; third-party inference extension shadowing the name match; partial upgrade where the extension binary is stale.","solutions":["Update the llamacpp extension to a version implementing `installBackend`.","Disable shadowing extensions.","Prefer the exact name lookup over the fuzzy fallback."],"exampleFix":"// before\nif (!extensionToUse || !('installBackend' in extensionToUse)) {\n  throw new Error('Extension does not support backend installation')\n}\n\n// after\nif (!extensionToUse || typeof extensionToUse.installBackend !== 'function') {\n  throw new Error(\n    'Installed llamacpp extension does not support manual backend installation. Update it.'\n  )\n}","handlingStrategy":"type-guard","validationCode":"if (!extensionToUse || typeof extensionToUse.installBackend !== 'function') {\n  toast.error('Incompatible extension', { description: 'Update the llamacpp extension to support manual backend install.' })\n  return\n}","typeGuard":"function supportsBackendInstall(ext: unknown): ext is { installBackend(filePath: string): Promise<void> } {\n  return !!ext && typeof (ext as any).installBackend === 'function'\n}","tryCatchPattern":"if (!supportsBackendInstall(extensionToUse)) {\n  toast.error('Extension does not support backend installation', { description: 'Update the llamacpp extension.' })\n  return\n}","preventionTips":["Prefer `typeof fn === 'function'` over `'fn' in obj`.","Keep the llamacpp extension version in sync with the host app.","Avoid the fuzzy matcher resolving to a non-llamacpp extension."],"tags":["llamacpp","extension","capability-check","install"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}