tinyhumansai/openhuman · error · Error
OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
Error message
OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
What it means
Thrown by startOpenAiCodexOAuth() after the core RPC 'openhuman.inference_openai_oauth_start' resolves but the result's authUrl field is missing, empty, or whitespace-only after trimming. The OpenHuman Rust core is expected to build a ChatGPT/OpenAI OAuth authorize URL (from its client-id config) and return it for an external-browser flow; this guard catches a core that answered the RPC without producing one. It is a client-side contract check, not a network error — the RPC itself succeeded.
Solutions
- Check the core log output for the inference/OAuth start handler — it usually logs why no authUrl was built (missing client id / endpoint config).
- Verify your core is current: the UI and openhuman-core must be from the same release; restart or update the core (restartCoreProcess or reinstall) so inference_openai_oauth_start returns auth_url.
- Confirm the Codex/OpenAI OAuth settings exist in Settings > AI providers, or that the .env / config TOML the core loads has the OAuth client values it needs.
- If running a standalone core (openhuman-core serve), point the app at the matching version or run the bundled desktop core instead.
Example fix
// before
const res = await callCoreRpc<{ result: OpenAiCodexOAuthStartResult }>({
method: 'openhuman.inference_openai_oauth_start',
params: {},
});
const authUrl = res?.result?.authUrl?.trim();
if (!authUrl) {
throw new Error(OPENAI_CODEX_OAUTH_MISSING_AUTH_URL);
}
// after — surface the raw core result to make triage possible
if (!authUrl) {
throw new Error(
`${OPENAI_CODEX_OAUTH_MISSING_AUTH_URL} (core result: ${JSON.stringify(res?.result ?? null)})`
);
} Defensive patterns
Strategy: try-catch
Validate before calling
import { callCoreRpc } from '../coreRpcClient';
async function canStartCodexOAuth(): Promise<boolean> {
try {
const res = await callCoreRpc<{ result?: { authUrl?: string } }>({
method: 'openhuman.inference_openai_oauth_start',
params: {},
});
return Boolean(res?.result?.authUrl?.trim());
} catch {
return false;
}
} Type guard
function hasAuthUrl(res: unknown): res is { authUrl: string } {
return typeof (res as { authUrl?: unknown })?.authUrl === 'string'
&& (res as { authUrl: string }).authUrl.trim().length > 0;
} Try / catch
try {
const { authUrl } = await startOpenAiCodexOAuth();
await openExternal(authUrl);
} catch (e) {
if (e instanceof Error && e.message === 'OPENAI_CODEX_OAUTH_MISSING_AUTH_URL') {
notify('Could not start Codex sign-in — update/restart the Core and retry.');
} else throw e;
} Prevention
- Keep app UI and openhuman-core on the same release; restart the core after updates.
- Surface the raw core result in the error message during development for fast triage.
- Verify OAuth client config (env/TOML) before shipping a settings screen that calls the flow.
When it happens
Trigger: Calling startOpenAiCodexOAuth() when: the core's Codex OAuth client credentials are unset or malformed; the core version predates inference_openai_oauth_start returning auth_url; the core handler hit an internal config error and returned an empty result object instead of an RPC error.
Common situations: Fresh desktop install where the backend/api config block is incomplete; running the UI against an older or standalone core binary (openhuman-core serve) that lacks the OAuth start handler's full response; a config migration wiped provider OAuth settings; environment (.env) missing required OAuth variables the core reads at startup.
Related errors
- Core returned an empty backend URL
- Model test RPC returned no result for
- oauthAuthReadinessUserMessage(quick.reason)
- OPENAI_CODEX_OAUTH_MISSING_CALLBACK_URL
- provider_surfaces_list_queue: unexpected empty response
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/6b6f7d3cc602eae0.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/api/aiSettingsApi.ts:726
/** Clear a stored API key. */
export async function clearCloudProviderKey(slug: string): Promise<void> {
if (slug === 'openhuman') {
return;
}
// Clear the new-style key. Legacy bare-slug entries are left as-is
// since we can't be sure they aren't used by other things.
await authRemoveProviderCredentials({ provider: authKeyForSlug(slug), profile: 'default' });
}
export async function startOpenAiCodexOAuth(): Promise<OpenAiCodexOAuthStartResult> {
const res = await callCoreRpc<{ result: OpenAiCodexOAuthStartResult }>({
method: 'openhuman.inference_openai_oauth_start',
params: {},
});
const authUrl = res?.result?.authUrl?.trim();
if (!authUrl) {
throw new Error(OPENAI_CODEX_OAUTH_MISSING_AUTH_URL);
}
return res.result;
}
export async function completeOpenAiCodexOAuth(callbackUrl: string): Promise<void> {
const callback = callbackUrl.trim();
if (!callback) {
throw new Error(OPENAI_CODEX_OAUTH_MISSING_CALLBACK_URL);
}
await callCoreRpc({
method: 'openhuman.inference_openai_oauth_complete',
params: { callback_url: callback },
});
}
export async function importOpenAiCodexCliAuth(): Promise<void> {
await callCoreRpc({ method: 'openhuman.inference_openai_oauth_import_codex_cli', params: {} });
}View on GitHub (pinned to 7491200858)