tinyhumansai/openhuman · error
OpenHuman uses the session JWT — keys are not configurable h
Error message
OpenHuman uses the session JWT — keys are not configurable here.
What it means
aiSettingsApi.setCloudProviderKey refuses the slug 'openhuman': OpenHuman's own inference path authenticates with the session JWT obtained at login, not with a user-entered API key, so there is nothing to store. The check happens before any credential write.
Source
Thrown at app/src/services/api/aiSettingsApi.ts:453
!!m &&
m.vision === e.vision &&
m.cost_per_1m_output === e.cost_per_1m_output &&
(m.cost_per_1m_input ?? 0) === (e.cost_per_1m_input ?? 0) &&
(m.cost_per_1m_cached_input ?? 0) === (e.cost_per_1m_cached_input ?? 0) &&
(m.context_window ?? 0) === (e.context_window ?? 0)
);
});
}
// ─── API key management (per cloud provider slug) ──────────────────────────
/**
* Store an API key for a cloud provider (encrypted at rest). Keyed by slug
* using the new `provider:<slug>` format.
*/
export async function setCloudProviderKey(slug: string, apiKey: string): Promise<void> {
if (slug === 'openhuman') {
throw new Error('OpenHuman uses the session JWT — keys are not configurable here.');
}
// Store under both new-style key `provider:<slug>` and legacy bare `<slug>`
// so old code paths that look up by bare slug continue to work.
await authStoreProviderCredentials({
provider: authKeyForSlug(slug),
profile: 'default',
token: apiKey,
setActive: true,
});
}
/**
* Outcome of a post-save connection check (#5146 §2.4).
*
* `ok: false` means the credential was stored but the provider could not
* actually serve an inference call — the "connected but unusable" state where
* the UI previously showed a healthy provider that failed on first real use.
*/View on GitHub (pinned to a221052e0d)
Solutions
- Filter the OpenHuman entry out of BYOK key-management UI, or render it as 'managed via your account login' with the input disabled
- If a settings import/migration script loops over slugs, skip 'openhuman' explicitly
- For OpenHuman auth problems, fix the login/session (re-auth), not the key store
Example fix
// before
providers.map(p => <KeyForm slug={p.slug} onSave={(k) => setCloudProviderKey(p.slug, k)} />);
// after
providers.map(p =>
p.slug === 'openhuman'
? <ManagedAuthNote key={p.slug} />
: <KeyForm key={p.slug} slug={p.slug} onSave={(k) => setCloudProviderKey(p.slug, k)} />
); Defensive patterns
Strategy: type-guard
Validate before calling
const isByokSlug = (slug: string): boolean => slug !== 'openhuman'; if (isByokSlug(slug)) await setCloudProviderKey(slug, apiKey); else showManagedAuthNotice();
Type guard
const isByokSlug = (slug: string): slug is Exclude<string, 'openhuman'> => slug !== 'openhuman';
Try / catch
try { await setCloudProviderKey(slug, apiKey); }
catch (e) { if (String(e.message).includes('session JWT')) showNotice('OpenHuman auth is handled by your login.'); else throw e; } Prevention
- Keep managed providers and BYOK providers in separate UI lists
- Render the OpenHuman row as login status, never as a key form
- Skip 'openhuman' in any slug-looping migration/import script
When it happens
Trigger: Calling setCloudProviderKey('openhuman', key) — e.g. a generic 'add API key' form that iterates provider slugs and includes the built-in OpenHuman entry, or a user pasting an OpenAI key while the OpenHuman row is selected.
Common situations: A provider settings list that mixes hosted OpenHuman with BYOK cloud providers (openai, anthropic, ...) and reuses one save handler; confusion between the OpenHuman account (JWT) and third-party provider keys.
Related errors
- Finish choosing how OpenHuman runs (tap Continue on the setu
- OpenHuman could not reach its remote (cloud) runtime. Check
- Invalid ${paramName}: ${String(value)}. Type must be an inte
- agentTeamApi: ${label} must be a positive integer
- agentTeamApi.get: teamId is required
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/edc40f4d180127b6.
Report an issue: GitHub.