{"record":{"id":"91f8311998f2493a","repo":"janhq/jan","slug":"critical-settings-llamacpp-version-llamacpp-b","errorCode":null,"errorMessage":"Critical settings \"llamacpp_version\" / \"llamacpp_backend\" not found.","messagePattern":"Critical settings \"llamacpp_version\" / \"llamacpp_backend\" not found\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"extensions/llamacpp-extension/src/index.ts","lineNumber":1505,"sourceCode":"          bestAvailableBackendString = preferredBackendString\n          logger.info(\n            `Using stored backend preference: ${bestAvailableBackendString}`\n          )\n        } else {\n          logger.warn(\n            `Stored backend type '${effectiveStoredBackendType}' not available, falling back to best backend`\n          )\n          // Clear the invalid stored preference\n          await this.clearStoredBackendType()\n          // bestAvailableBackendString remains as the priority one calculated earlier\n        }\n      }\n\n      let settings = structuredClone(SETTINGS)\n      const versionSetting = settings.find((s) => s.key === 'llamacpp_version')\n      const backendSetting = settings.find((s) => s.key === 'llamacpp_backend')\n      if (!versionSetting || !backendSetting) {\n        throw new Error(\n          'Critical settings \"llamacpp_version\" / \"llamacpp_backend\" not found.'\n        )\n      }\n\n      // Read prior persisted values (may have been pre-populated by the\n      // legacy-migration pass in onLoad, or carry user-edited values from a\n      // prior session).\n      const priorPersisted = await this.getSettings()\n      const priorVersion = String(\n        priorPersisted.find((s) => s.key === 'llamacpp_version')?.controllerProps\n          .value ?? ''\n      )\n      const priorBackend = String(\n        priorPersisted.find((s) => s.key === 'llamacpp_backend')?.controllerProps\n          .value ?? ''\n      )\n\n      // Flag versions already on disk so the dropdown distinguishes a rollback","sourceCodeStart":1487,"sourceCodeEnd":1523,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/llamacpp-extension/src/index.ts#L1487-L1523","documentation":"Invariant assertion: the SETTINGS template (a static constant) must contain entries with keys 'llamacpp_version' and 'llamacpp_backend'. If structuredClone(SETTINGS) yields an array where either find() returns undefined, the extension considers itself corrupt and throws. This is a developer/code-level error, not a runtime/user configuration error.","triggerScenarios":"The SETTINGS constant was modified and one of the two critical entries was removed or its key was renamed. priorPersisted values are read afterward, but the check runs against the template first, so this fires before any persisted-data logic.","commonSituations":"A code refactor renamed llamacpp_version or llamacpp_backend to a new key without updating this assertion; a merge accidentally dropped one of the entries; a settings schema migration left the template incomplete.","solutions":["Restore the 'llamacpp_version' and 'llamacpp_backend' entries in the SETTINGS constant.","If the keys were intentionally renamed, update this assertion and all dependent code paths that reference the old key names.","Add a unit test that validates SETTINGS always contains both critical keys to catch regressions."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const SETTINGS_KEYS = new Set(SETTINGS.map(s => s.key))\nif (!SETTINGS_KEYS.has('llamacpp_version') || !SETTINGS_KEYS.has('llamacpp_backend')) {\n  throw new Error('SETTINGS template is missing critical keys — code regression')\n}","typeGuard":"function hasCriticalSettings(settings: { key: string }[]): boolean {\n  const keys = new Set(settings.map(s => s.key))\n  return keys.has('llamacpp_version') && keys.has('llamacpp_backend')\n}","tryCatchPattern":null,"preventionTips":["Add a unit test asserting SETTINGS always contains llamacpp_version and llamacpp_backend.","Review any PR that touches the SETTINGS constant to ensure critical entries are preserved.","Use a TypeScript satisfy or const assertion to lock the required keys at compile time."],"tags":["settings","invariant","configuration","developer-error","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}