{"record":{"id":"edc40f4d180127b6","repo":"tinyhumansai/openhuman","slug":"openhuman-uses-the-session-jwt-keys-are-not-conf","errorCode":null,"errorMessage":"OpenHuman uses the session JWT — keys are not configurable here.","messagePattern":"OpenHuman uses the session JWT — keys are not configurable here\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"app/src/services/api/aiSettingsApi.ts","lineNumber":453,"sourceCode":"      !!m &&\n      m.vision === e.vision &&\n      m.cost_per_1m_output === e.cost_per_1m_output &&\n      (m.cost_per_1m_input ?? 0) === (e.cost_per_1m_input ?? 0) &&\n      (m.cost_per_1m_cached_input ?? 0) === (e.cost_per_1m_cached_input ?? 0) &&\n      (m.context_window ?? 0) === (e.context_window ?? 0)\n    );\n  });\n}\n\n// ─── API key management (per cloud provider slug) ──────────────────────────\n\n/**\n * Store an API key for a cloud provider (encrypted at rest). Keyed by slug\n * using the new `provider:<slug>` format.\n */\nexport async function setCloudProviderKey(slug: string, apiKey: string): Promise<void> {\n  if (slug === 'openhuman') {\n    throw new Error('OpenHuman uses the session JWT — keys are not configurable here.');\n  }\n  // Store under both new-style key `provider:<slug>` and legacy bare `<slug>`\n  // so old code paths that look up by bare slug continue to work.\n  await authStoreProviderCredentials({\n    provider: authKeyForSlug(slug),\n    profile: 'default',\n    token: apiKey,\n    setActive: true,\n  });\n}\n\n/**\n * Outcome of a post-save connection check (#5146 §2.4).\n *\n * `ok: false` means the credential was stored but the provider could not\n * actually serve an inference call — the \"connected but unusable\" state where\n * the UI previously showed a healthy provider that failed on first real use.\n */","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/api/aiSettingsApi.ts#L435-L471","documentation":"setCloudProviderKey(slug, apiKey) stores a per-provider API key via authStoreProviderCredentials using the 'provider:<slug>' key format. The 'openhuman' slug is explicitly rejected because OpenHuman's own inference/auth uses the session JWT — there is no user-configurable API key for it, so attempting to store one throws this explanatory error before any storage call.","triggerScenarios":"Calling setCloudProviderKey('openhuman', ...) — typically from a settings screen that renders the same form for every provider slug, or from import/sync code that bulk-writes all provider keys including the OpenHuman entry.","commonSituations":"Generic provider-key UI not special-casing the built-in provider; migration scripts copying keys across profiles without filtering; QA/test harness iterating all slugs.","solutions":["Filter the 'openhuman' slug out before calling — never send it to setCloudProviderKey.","In the settings UI, hide the API-key input for the openhuman provider and show 'uses your OpenHuman login' instead.","For tests, mock the function or skip the slug rather than expecting storage to no-op.","If OpenHuman auth is failing, the fix is signing in (session JWT), not setting a key."],"exampleFix":"// before\nfor (const [slug, key] of Object.entries(keys)) {\n  await setCloudProviderKey(slug, key);\n}\n\n// after\nfor (const [slug, key] of Object.entries(keys)) {\n  if (slug === 'openhuman') continue; // uses session JWT, no key\n  await setCloudProviderKey(slug, key);\n}","handlingStrategy":"validation","validationCode":"const USER_KEY_PROVIDERS = new Set(['openhuman']);\n\nfunction isKeyConfigurable(slug: string): boolean {\n  return !USER_KEY_PROVIDERS.has(slug);\n}\nif (isKeyConfigurable(slug)) {\n  await setCloudProviderKey(slug, apiKey);\n}","typeGuard":"function isConfigurableProviderSlug(slug: string): boolean {\n  return slug !== 'openhuman';\n}","tryCatchPattern":"try {\n  await setCloudProviderKey(slug, apiKey);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('keys are not configurable')) {\n    return; // expected for the openhuman slug — no-op, not an error state\n  }\n  throw err;\n}","preventionTips":["Special-case the built-in provider in settings UI: show 'uses your OpenHuman login' instead of a key field.","Filter the openhuman slug in bulk import/sync loops before calling setCloudProviderKey.","For OpenHuman auth problems, route users to sign-in (session JWT), never to key entry."],"tags":["api-key","provider","settings","openhuman","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}