moeru-ai/airi · error · Error

No authorization handler is registered for this app runtime.

Error message

No authorization handler is registered for this app runtime.

What it means

signInOIDC requires a runtime-specific authorization handler (registered elsewhere for web vs Electron) that knows how to navigate to the provider's authorization URL. If no handler was set before sign-in, the library cannot navigate and throws immediately.

Source

Thrown at packages/stage-ui/src/libs/auth.ts:117

    return false

  const persisted = consumeFlowState()
  if (!persisted)
    throw new Error('OIDC flow status has expired or is no longer valid.')

  const tokens = await exchangeCodeForTokens(code, persisted.flowState, persisted.params, state)
  await applyOIDCTokens(tokens, persisted.params.clientId)
  return true
}

/**
 * Initiate OIDC Authorization Code + PKCE sign-in flow.
 * Builds the authorization URL, persists PKCE state, and navigates.
 */
export async function signInOIDC(params: OIDCFlowParams) {
  const handler = authorizationHandler
  if (!handler)
    throw new Error('No authorization handler is registered for this app runtime.')

  const { provider, ...oidcParams } = params
  const { url, flowState } = await buildAuthorizationURL(oidcParams)
  persistFlowState(flowState, params)

  const result = await handler({
    authorizationUrl: url.toString(),
    provider,
  })
  if (result?.callbackUrl)
    await completeOIDCSignIn(result.callbackUrl)
}

/**
 * Trigger the project-default OIDC sign-in flow.
 *
 * Use when:
 * - Any UI surface needs to start a login (top-nav button, 401 handler,

View on GitHub (pinned to 0616eabd5b)

Solutions

  1. Register the authorization handler for your runtime before any sign-in call (find the app's auth bootstrap, e.g. where the Electron or web handler is installed).
  2. If adding a new host/runtime, provide a handler that performs the navigation (window.location or Electron shell.openExternal) at startup.
  3. Guard UI: disable the sign-in button until the auth runtime is initialized.
  4. In tests, register a mock handler or assert the throw as expected pre-init behavior.

Example fix

// before
await signInOIDC(params) // throws: no handler registered

// after
// during app bootstrap (once)
setAuthorizationHandler(async ({ url }) => {
  window.location.assign(url)
})
await signInOIDC(params)
Defensive patterns

Strategy: validation

Validate before calling

if (!isAuthorizationHandlerRegistered()) { // expose a probe from the auth lib
  disableSignInUI()
} else {
  enableSignInUI()
}

Type guard

null

Try / catch

try {
  await signInOIDC(params)
} catch (err) {
  if (err instanceof Error && err.message.includes('No authorization handler')) {
    showSetupError('Sign-in is not configured for this runtime.')
  } else throw err
}

Prevention

When it happens

Trigger: Calling signInOIDC (directly or via triggerSignIn) before the app runtime registered its authorization handler (e.g. setAuthorizationHandler / initialization was skipped); running in an environment whose bootstrap code path never registers a handler; module initialization ordering issues where sign-in fires before app setup completes.

Common situations: Unit tests or Storybook harnesses that render a sign-in button without the app bootstrap; a new host app (Electron window, mobile webview) reusing stage-ui without wiring the handler; a refactor that moved handler registration into a lazily-loaded module; race where a deep-link auto-sign-in runs before setup.

Related errors


AI-assisted analysis of moeru-ai/airi@0616eabd5b (2026-08-28). Data as JSON: /api/errors/f2b5b8a5db357faa. Report an issue: GitHub.