{"record":{"id":"7b87c36eb07a081d","repo":"janhq/jan","slug":"extension-does-not-support-backend-updates","errorCode":null,"errorMessage":"Extension does not support backend updates","messagePattern":"Extension does not support backend updates","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/hooks/useBackendUpdater.ts","lineNumber":323,"sourceCode":"          (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 (\n        !extensionToUse ||\n        !('getSettings' in extensionToUse) ||\n        !('updateBackend' in extensionToUse)\n      ) {\n        throw new Error('Extension does not support backend updates')\n      }\n\n      const extension = extensionToUse as LlamacppExtension\n\n      // Use the exact target backend from checkBackendForUpdates if available,\n      // to avoid mismatches between old/new backend name formats\n      let targetBackendString = updateState.updateInfo.targetBackend\n\n      if (targetBackendString) {\n        // Validate and normalize the provided target backend string\n        const rawParts = targetBackendString.split('/')\n        const versionPart = rawParts[0]?.trim()\n        const backendTypePart = rawParts[1]?.trim()\n\n        if (rawParts.length !== 2 || !versionPart || !backendTypePart) {\n          // Malformed targetBackend; fall back to constructing from current settings\n          const currentBackendType = await getCurrentBackendTypeFromSettings(\n            extension","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/hooks/useBackendUpdater.ts#L305-L341","documentation":"Thrown when an extension was found (either by name or via the fuzzy fallback) but it lacks the `getSettings` or `updateBackend` methods — i.e. it is not the llamacpp extension or is an older/incompatible version. The `'method' in object` duck-type check is the capability gate.","triggerScenarios":"The fuzzy matcher picked the wrong extension (its constructor name coincidentally contained 'llamacpp' or its type contained 'inference') but that extension does not implement backend updates; or the installed llamacpp extension is an old version predating `updateBackend`.","commonSituations":"Another inference extension shadows llamacpp; extension version mismatch after partial upgrade; a custom/third-party extension named similarly but lacking the API.","solutions":["Update the llamacpp extension to a version that implements `updateBackend`.","Disable other extensions whose names/type strings could shadow the fuzzy matcher.","Prefer the exact `getByName('llamacpp-extension')` result and only fall back with a stricter type check."],"exampleFix":"// before\nif (!extensionToUse || !('getSettings' in extensionToUse) || !('updateBackend' in extensionToUse)) {\n  throw new Error('Extension does not support backend updates')\n}\n\n// after\nif (!extensionToUse || typeof extensionToUse.updateBackend !== 'function') {\n  throw new Error(\n    'Installed llamacpp extension does not support backend updates. Update the extension.'\n  )\n}","handlingStrategy":"type-guard","validationCode":"if (!extensionToUse || typeof extensionToUse.updateBackend !== 'function' || typeof extensionToUse.getSettings !== 'function') {\n  toast.error('Incompatible extension', { description: 'Update the llamacpp extension to support backend updates.' })\n  return\n}","typeGuard":"function supportsBackendUpdates(ext: unknown): ext is LlamacppExtension {\n  return !!ext && typeof (ext as any).getSettings === 'function' && typeof (ext as any).updateBackend === 'function'\n}","tryCatchPattern":"if (!supportsBackendUpdates(extensionToUse)) {\n  toast.error('Extension does not support backend updates', { description: 'Update the llamacpp extension.' })\n  return\n}","preventionTips":["Use `typeof fn === 'function'` rather than `'fn' in obj` — it catches non-function shadowing.","Update the llamacpp extension whenever the host app is upgraded.","Avoid the fuzzy matcher picking a non-llamacpp inference extension."],"tags":["llamacpp","extension","capability-check","backend"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}