Skip to content

Error codes

Like system.devices, the security ops do not use string error codes; they encode failures as { ok: false, error?: string } returns or HTTP status codes for HTTP endpoints.

system.auth — bus op failures

Session ops

OpFailure returnCause
auth.session.validate{ ok: false, error: 'invalid' }bad signature, wrong issuer, expired, or jti revoked
auth.session.create(throws if secret too short)construction-time, not runtime
auth.session.revoke{ ok: true, revoked: false }no extractable token in headers

Identity ops

OpFailure returnCause
auth.identity.resolve{ authenticated: false, principalId: null, ... }no valid session in headers
auth.principal.ensure{ ok: false, error: '...' }invalid issuer/subject; principal store error
auth.principal.get{ ok: false }principal id not found
OpFailure returnCause
auth.hostLink.create(throws)missing required principalId, spaceId, or authorityRoot
auth.hostLink.get{ ok: false }not found, or scope filter rejected
auth.hostLink.refresh{ ok: false }not found, scope mismatch, or status revoked
auth.hostLink.revoke{ ok: true, alreadyRevoked: true }already revoked (idempotent)
auth.hostLink.verifyHeartbeat{ ok: false }bearer hash mismatch, status revoked, or no heartbeatTokenHash set

Device-flow ops

OpFailure returnCause
auth.device.start(always succeeds)n/a
auth.device.status{ ok: false }not found
auth.device.approve{ ok: false, error: '...' }not found, status cancelled/exchanged, or principal namespace required
auth.device.poll{ ok: true, status: '<current>' }reflects current state; not an error
auth.device.exchange{ ok: false }not in approved state
auth.device.cancel{ ok: true }always succeeds (idempotent)

Pair ops

Symmetric to device-flow ops with pairRequestId instead of deviceCode/userCode.

Namespace ops

OpFailure returnCause
auth.namespace.check{ ok: false, available: false, error: 'Invalid public namespace' }doesn't match PUBLIC_NAMESPACE_PATTERN
auth.namespace.checkRouteKeysimilardoesn't match ROUTE_KEY_PATTERN, is reserved, or DNS-like
auth.namespace.claim{ ok: false, error: 'Principal not found: <id>' }principal doesn't exist
{ ok: false, error: 'domain.* namespaces require DNS verification' }domain.* not yet implemented
{ ok: false, error: 'system.* namespaces are reserved' }reserved
{ ok: false, error: 'Public namespace already claimed: <ns>' }duplicate
{ ok: false, error: 'Route key already claimed: <key>' }duplicate
{ ok: false, error: 'Parent namespace is not delegated to <id>' }nested claim under another principal's parent
auth.namespace.resolve{ ok: true, claim: null }not claimed

Google OIDC ops

OpFailure returnCause
auth.google.status{ ok: true, configured: false }no Google client configured
auth.google.login{ ok: false, error: 'not configured' }Google client missing
auth.google.callback{ ok: false, error: 'state expired' }pending login pruned
{ ok: false, error: 'token exchange failed' }upstream OAuth error
{ ok: false, error: 'invalid id_token' }signature/iss/aud/exp check failed
{ ok: false, error: 'email not verified' }email_verified !== true

system.factotum — bus op failures

OpFailure returnCause
credential.store{ ok: false }provider/type missing or type-specific required fields missing
credential.get{ found: false }no row for provider
credential.delete{ ok: false }no row for provider
credential.refresh{ ok: false }not OAuth, no refresh token, or expired
credential.validate{ ok: false, error: '...' }API call returned non-2xx; specific 401/403/network messages included
credential.import-detected(always succeeds)returns empty detected: [] if nothing found
credential.import{ ok: false }source/provider mismatch or file unreadable
credential.lease{ ok: false, error: 'provider is required' }missing provider
{ ok: false, error: 'No credential found for provider: X' }also emits factotum.needkey
credential.materialize{ ok: false, error: 'leaseId is required' }missing leaseId
{ ok: false, error: 'Lease not found or expired' }lease consumed or never existed
{ ok: false, error: 'Lease expired' }TTL passed
{ ok: false, error: 'Credential no longer available' }row deleted between lease and materialize

HTTP endpoint statuses

The HTTP gateway (@open-matrix/system-gateway-http) translates auth failures to HTTP status codes:

EndpointStatusCause
any auth-required401no session cookie / Bearer token
any auth-required403session valid but principal lacks capability for this resource
/api/auth/login/google302redirect to Google (success)
/api/auth/callback/google302redirect to returnTo after success
/api/auth/callback/google4xxcode exchange failed
/_auth/host-link/heartbeat200success
/_auth/host-link/heartbeat401no/bad bearer
/_auth/host-link/heartbeat403bearer valid but link revoked, or body identity mismatch
/_auth/host-link/heartbeat404hostLinkId not found

Common return-shape conventions

Every op:

  • Returns { ok: true, ... } on success.
  • Returns { ok: false, error?: string } on failure (or returns null from store methods that the bus layer wraps).
  • Returns { ok: true, found: false } for "not found" if the op is conceptually a query (e.g. credential.get).

Callers MUST check ok === true before treating the data as authoritative. Callers SHOULD log the error string on the unhappy path before surfacing to the user.

See also

Source: projects/matrix-3/packages/system-auth/src/host-auth.ts (return paths in stores); projects/matrix-3/packages/system-factotum/dist/index.js (return paths in FactotumActor).