Skip to content

Error codes

All billing-API errors are JSON: {"error": "<message>"}.

HTTP Cause Typical message Retry?
400 Bad Request Invalid request: malformed JSON, unknown field, value out of range, more than 5,000 usage records, revoking your own key invalid request: … No — fix the request
401 Unauthorized Missing, malformed, unknown or revoked key, or the wrong kind of key (relay key on a backend route, backend key on /v1/usage) invalid api key No
402 Payment Required Tenant has never paid payment required: add credit to activate this tenant After paying
402 Payment Required Prepaid balance spent insufficient credit: top up to admit new sessions After topping up
403 Forbidden Tenant suspended, archived or deleted tenant is not active No — contact support
404 Not Found No such key or tenant not found No
409 Conflict Already exists, or a tenant status change that is not allowed already exists / tenant status cannot change that way No
429 Too Many Requests More than 5 signups per hour from one address too many signups from this address Later
500 Internal Server Error MOQOM bug internal error Yes, with backoff
502 Bad Gateway Payment provider (Stripe) returned an error Stripe’s message Yes, with backoff
503 Service Unavailable Payments not configured on this deployment payments are not configured on this deployment No

Authentication failures are deliberately uninformative: you are never told which part of a key was wrong.

The Join endpoint returns plain-text errors.

HTTP Cause
400 Unreadable body, missing device key, mismatched key and thumbprint, invalid name
401 Unknown credential, or a relay credential
402 Tenant has no credit (never paid, or balance spent)
403 Credential has no publish rights, or permission denied
404 Room not found
405 Method other than POST
409 Room ended, or another precondition failed
429 More than 30 requests per minute for this credential
503 / 504 Temporarily unavailable / deadline exceeded
500 Internal error
Code Cause Retry?
UNAUTHENTICATED No credentials, empty credential, or unknown key No
PERMISSION_DENIED Request names another tenant; relay key used on the admin API; actor lacks capability or standing over the target; minting beyond the key’s ceiling No
INVALID_ARGUMENT Missing tenant or device_thumbprint; malformed name, CIDR or capability; token lifetime above 15 minutes; changing an immutable policy field No
NOT_FOUND No such room, participant or watchdog — also returned for resources in another tenant No
ALREADY_EXISTS Room already exists No
FAILED_PRECONDITION Room has ended; room requires age verification; tenant has no credit (MintClientToken only) After fixing the cause
CANCELED / DEADLINE_EXCEEDED Client cancelled or timed out Yes
UNAVAILABLE Transient Yes — same idempotency key
INTERNAL MOQOM bug; the message is kept to help diagnosis Report it
gRPC code Go sentinel Rust
NOT_FOUND ErrNotFound Error::NotFound
PERMISSION_DENIED ErrDenied Error::Denied
UNAUTHENTICATED ErrUnauthenticated Error::Unauthenticated
INVALID_ARGUMENT ErrInvalid Error::Invalid
ALREADY_EXISTS ErrExists Error::Exists
FAILED_PRECONDITION (room ended) ErrClosed Error::Closed
UNAVAILABLE ErrUnavailable Error::Unavailable
INTERNAL ErrInternal Error::Internal
Operation Without credit
POST /join 402
MintClientToken FAILED_PRECONDITION
Self-hosted relay POST /v1/usage 200, with "admitted": false
Moderation (Kick, Ban, ForceMute, …) Always works
Rooms, events, keys, billing routes Always work
TerminalEvent Meaning
.moderated(code:) Kicked, banned or room closed by a moderator, with a moderation code
.hostEnded The host ended the room or broadcast
.networkFailure The network did not come back within the reconnect window
.tokenExpired The token lapsed and was not renewed

MoqomError.encryptionRequired is not terminal. startBroadcast and startAudio throw it when the room requires end-to-end encryption and useEncryption has not been called; set a key and try again. Incoming media dropped for the same reason is reported as RoomEvent.encryptionRequired(participant). See End-to-end encryption.