Livqeno Docs

Errors

Five error vocabularies, why they are separate, and every code in each with its cause and fix.

Livqeno has five error vocabularies. They are separate on purpose: a chat failure, a media failure and a shader failure have almost nothing in common, and merging them would produce a list that describes none of them well.

VocabularyWhere you see itCount
RAVEN_*The code field of any HTTP error body29
RTCErrorCode@ravenkash/rtc throws and error events13
ChatErrorCodeThe chat WebSocket error frame and @ravenkash/chat26
SignalingErrorCodeThe RTC signaling WebSocket error frame15
EffectsErrorCode@ravenkash/effects5

Plus RTC error categories, which are a server-side classification of a failure that already happened — not a response code.

The HTTP error envelope

{
  "code": "RAVEN_ROOM_NOT_FOUND",
  "legacyCode": "NOT_FOUND",
  "message": "Room not found",
  "requestId": "req_9f2c41ab77e0c3d5b1a4e8f2",
  "path": "/v1/rooms/room_missing"
}
FieldNotes
codeThe canonical code. Switch on this.
legacyCodeDeprecated. What that error used to emit before the namespace existed. Nothing in Livqeno reads it.
messageHuman-readable, safe to log, never contains credentials or internals.
requestIdAlso returned as the x-request-id header, always the same value. Quote it in a bug report.
pathThe route that produced the error.

Some errors add fields — a 429 carries retryAfterSeconds. Ignore fields you do not recognise rather than treating them as an error.

HTTP error codes

Authentication and authorization

CodeHTTPCauseFix
RAVEN_AUTH_ERROR401Credential missing, malformed, or rejectedCheck the Authorization header and that the key was not revoked
RAVEN_TOKEN_EXPIRED401The token expiredMint a fresh one. Do not re-authenticate the user
RAVEN_PERMISSION_DENIED403Authenticated, but not allowedCheck the token's permissions, or the caller's project role
RAVEN_OAUTH_ERROR401OAuth sign-in could not complete — bad or expired state, failed code exchange, or the person cancelledAlways safe to retry from the start of the flow
RAVEN_OAUTH_EMAIL_UNAVAILABLE400The provider returned no usable email, and Livqeno accounts are keyed by emailFix is at the provider — e.g. GitHub with no verified primary address
RAVEN_OAUTH_EMAIL_UNVERIFIED403An account exists for this email but the provider has not verified itVerify at the provider. Linking otherwise would allow account takeover

Not found

CodeHTTPCause
RAVEN_NOT_FOUND404Generic — no resource-specific code fits
RAVEN_PROJECT_NOT_FOUND404No such project, or not yours
RAVEN_ROOM_NOT_FOUND404An RTC room
RAVEN_CONVERSATION_NOT_FOUND404A chat conversation
RAVEN_MESSAGE_NOT_FOUND404No such message in this project
RAVEN_ATTACHMENT_NOT_FOUND404No such attachment, or not yet uploaded
RAVEN_STREAM_NOT_FOUND404A live stream
RAVEN_RTC_SERVER_NOT_FOUND404No media server by that name in the fleet

Most 404s here are environment mismatches: a development key cannot see a production room, and the room genuinely does not exist as far as that key is concerned.

Conflict

CodeHTTPCauseFix
RAVEN_CONFLICT409Generic — a name taken, a state already reached
RAVEN_MESSAGE_ALREADY_EXISTS409A clientMessageId was replayedNothing — this is idempotency working. Treat it as success
RAVEN_CONVERSATION_ARCHIVED409Writes are closed; reads still workUnarchive it first
RAVEN_STREAM_INVALID_STATE409Invalid from the stream's current status — starting an already-LIVE stream, anything on an ENDED oneRead the status first. ENDED is terminal

Request problems

CodeHTTPCauseFix
RAVEN_VALIDATION_FAILED400Body or query malformed — including an unknown field, which is rejected rather than ignoredCheck spelling against the parameter tables
RAVEN_INVALID_CURSOR400Pagination cursor unreadableRestart the page sequence. Do not silently fall back to page one
RAVEN_PAYLOAD_TOO_LARGE413Generic size limit
RAVEN_MESSAGE_TOO_LARGE413Message text or metadata over its limit4000 chars / 4096 bytes by default
RAVEN_ATTACHMENT_TOO_LARGE413Over STORAGE_MAX_ATTACHMENT_BYTES25 MB by default
RAVEN_RATE_LIMITED429A budget was exceeded. Carries retryAfterSecondsBack off by that value, not a fixed interval

MESSAGE_TOO_LARGE and ATTACHMENT_TOO_LARGE are separate because the two limits are configured independently — "make it smaller" is not actionable until you know which limit you crossed.

Infrastructure

CodeHTTPCauseFix
RAVEN_CONNECTION_FAILEDA realtime connection could not be establishedSee RTC troubleshooting
RAVEN_NO_RTC_CAPACITYNo healthy media server had roomAn operator problem, not a caller one. Check the fleet
RAVEN_WEBHOOK_FAILEDA webhook delivery failedCheck the deliveries endpoint
RAVEN_NOT_CONFIGURED501The deployment has not enabled this feature — most often attachments with no STORAGE_BUCKETAn operator fix
RAVEN_INTERNAL_ERROR500The only code an unexpected exception surfaces asQuote the requestId

Server-SDK-local codes

Raised by @ravenkash/server and raven-sdk before a request leaves the process, so they never appear in an HTTP body — but they share the namespace so one switch covers everything:

CodeCause
RAVEN_INVALID_CONFIGNo config object, or a missing apiKey
RAVEN_TIMEOUTThe request exceeded the client timeout (10s default)
RAVEN_NETWORK_ERRORThe request never reached Livqeno
RAVEN_UNKNOWN_ERRORNothing more specific could be determined

When a proxy returns an HTML error page instead of JSON, the SDK derives the code from the status — and derives it to the same name the API would have sent, so a 401 is RAVEN_AUTH_ERROR either way.

legacyCode and the migration

Before this namespace existed, code held bare values: NOT_FOUND, UNAUTHORIZED, VALIDATION_FAILED. Every error body now carries both.

if (error.code === 'NOT_FOUND') { … }        // old — now error.legacyCode
if (error.code === 'RAVEN_ROOM_NOT_FOUND') { … }   // new

legacyCode is lossy in one direction — several canonical codes map back to the same legacy value. That is the point: the new codes carry information the old ones did not. It is deprecated and will be removed.

RTC SDK errors

RTCError is the only error type @ravenkash/rtc throws or emits. Never a raw browser DOMException.

CodeCauseFix
INVALID_TOKENMalformed, or missing token/endpoint in the configForward the mint response untouched
TOKEN_EXPIREDAlready expired when the client was createdMint on demand, not at page load
ROOM_NOT_FOUNDjoin() was given a room the token was not minted forPass the room id or name from the mint response
PERMISSION_DENIEDThe token does not grant thisFix the permissions at mint time
CAMERA_PERMISSION_DENIEDThe user denied camera accessPrompt in your own UI; the OS will not ask twice
MICROPHONE_PERMISSION_DENIEDThe user denied microphone accessAs above
DEVICE_NOT_FOUNDNo such device, or it was unpluggedRe-enumerate with getDevices()
NETWORK_ERRORA network-level failure
SIGNALING_ERRORThe signaling handshake did not completeCheck endpoint is reachable and wss://
MEDIA_ERRORA media operation failed — worth retrying
NOT_SUPPORTEDThe platform cannot do this at all, e.g. screen share with no getDisplayMediaPermanent. Hide the button rather than retrying
CONNECTION_FAILEDICE/DTLS did not completeUsually TURN. See troubleshooting
TIMEOUTAn operation exceeded its deadline

NOT_SUPPORTED and MEDIA_ERROR are deliberately distinct: one is a permanent fact about the device that a UI should act on, the other is a failure worth retrying.

import { isRTCError } from '@ravenkash/rtc';
 
room.on('error', (error) => {
  if (!isRTCError(error)) return;
  if (error.code === 'CAMERA_PERMISSION_DENIED') showPermissionHelp();
  if (error.code === 'NOT_SUPPORTED') hideFeature();
});

RTC error categories

A classification applied server-side to a failure a client reported. You see these in the dashboard, in raven errors list, and on the observability API — never as a response code.

CategoryMeaning
AUTHENTICATION_ERRORThe caller's own credential was rejected
AUTHORIZATION_ERRORAuthenticated, but not allowed
TOKEN_ERRORThe RTC token was invalid, malformed, or expired
SIGNALING_ERRORThe signaling handshake did not complete
ICE_ERRORICE connectivity checks failed — usually a firewall or NAT
TURN_ERRORA TURN relay connection specifically could not be established
SFU_ERRORThe media server could not complete, for no more specific reason
NETWORK_ERRORA generic network failure or timeout
CLIENT_ERRORA local issue — wrong room, device permission, media error
UNKNOWN_ERRORNothing more specific could be determined

CONNECTION_FAILED is context-dependent, resolved in this order: a turn_unreachable hint → TURN_ERROR; a failed iceConnectionStateICE_ERROR; signaling never reaching stable → SIGNALING_ERROR; otherwise SFU_ERROR.

Every classified error carries a likelyCause and suggestedAction, deliberately hedged ("likely a firewall/NAT restriction") rather than a claim of certainty a server cannot back up.

Chat errors

26 codes on the @ravenkash/chat side, 22 of which the gateway can put on an error frame. They map one-to-one onto SDK error classes so you can branch on the class rather than string-matching.

CodeHTTPSDK classMeaning
INVALID_TOKEN401RavenChatAuthenticationErrorMissing, malformed, or wrongly-signed
TOKEN_EXPIRED401RavenChatAuthenticationErrorMint a new one — wire onTokenExpiring
TOKEN_REVOKED401RavenChatAuthenticationErrorRevoked before its natural expiry
UNAUTHORIZED401RavenChatAuthenticationErrorNo usable credential presented
PERMISSION_DENIED403RavenChatPermissionErrorThe scope or role does not allow this
NOT_A_MEMBER403RavenChatPermissionErrorNot a member of that conversation
ORIGIN_NOT_ALLOWED403RavenChatPermissionErrorThe upgrade's Origin is not in CORS_ORIGIN
ROOM_NOT_FOUND404RavenRoomErrorNo such conversation in this project
NOT_IN_ROOM400RavenRoomErrorThis connection is not subscribed to that room
TOO_MANY_SUBSCRIPTIONS400RavenRoomErrorPer-connection subscription limit reached
CONVERSATION_ARCHIVED409RavenRoomErrorWrites closed; reads still work
MESSAGE_NOT_FOUND404RavenMessageError
MESSAGE_DELETED409RavenMessageErrorThe message is soft-deleted
MESSAGE_TOO_LARGE413RavenMessageErrorText, metadata, or frame over its limit
INVALID_MESSAGE400RavenMessageErrorMalformed or missing a required field
INVALID_MESSAGE_TYPE400RavenMessageErrorUnsupported frame or message type
INVALID_CURSOR400RavenMessageErrorPagination cursor malformed
RATE_LIMITED429RavenRateLimitErrorCarries retryAfterSeconds
ATTACHMENT_NOT_FOUND404RavenAttachmentError
ATTACHMENTS_NOT_CONFIGURED501RavenAttachmentErrorNo object storage on this deployment
ATTACHMENT_TOO_LARGE413RavenAttachmentErrorOver STORAGE_MAX_ATTACHMENT_BYTES
CONNECTION_FAILEDRavenChatConnectionErrorCould not connect, or reconnects exhausted
CONNECTION_CLOSEDRavenChatConnectionErrorThe socket closed before the server replied
NETWORK_ERRORRavenChatConnectionErrorThe request never reached Livqeno
TIMEOUTRavenChatConnectionErrorNo response within the request timeout
INTERNAL_ERROR500RavenChatErrorLogged server-side in full

An unrecognised code from a newer server becomes a base RavenChatError with the code preserved, rather than an exception — an older client keeps working across a server upgrade.

Raw infrastructure failures never reach a client. A Postgres constraint violation or a Redis timeout is logged server-side and surfaces as INTERNAL_ERROR.

Chat WebSocket close codes

CodeMeaningReconnect?
1000Normal closureNo
4401Authentication failedNo — retrying cannot help
4403Origin not allowedNo — fix CORS_ORIGIN
4429Connection rate limitYes, after backing off
4440Token expiredYes, with a fresh token
4500Server shutting downYes, after backing off — a deploy, not a fault

@ravenkash/chat treats 4401 and 4403 as terminal and reports failed rather than retrying forever.

Signaling errors

The RTC signaling WebSocket keeps its own vocabulary — it is a separately versioned wire protocol. You see these on an error frame, and the SDK maps most of them onto an RTCError.

CodeMeaningRetryable?
INVALID_TOKENMalformed or wrongly-signedNo
TOKEN_EXPIREDExpired before or during connectYes, with a fresh token
UNAUTHORIZEDNo usable credentialNo
ROOM_NOT_FOUNDNo such room for this project and environmentNo
ROOM_FULLAt SIGNALING_MAX_PARTICIPANTS_PER_ROOMNo
INVALID_MESSAGEMalformed frameNo
INVALID_MESSAGE_TYPEUnsupported frame typeNo
PARTICIPANT_NOT_FOUNDNamed participant is not in the roomNo
NOT_IN_ROOMAn operation before joiningNo
PERMISSION_DENIEDThe token does not grant this — e.g. publishing without publishNo
RATE_LIMITEDPer-connection message budget exceededYes, after backing off
NO_RTC_CAPACITYNo healthy media server had roomAn operator problem
RTC_SERVER_UNREACHABLEThe allocated server could not be reachedYes
NEGOTIATION_FAILEDNot recoverable without rejoiningNo — rejoin
NEGOTIATION_GLAREAn offer is already in flightYes — answer the offer already arriving, then retry

Full frame contract in Signaling protocol.

Effects errors

CodeCauseFix
RAVEN_EFFECT_UNSUPPORTEDUnknown filter type, or no usable engine on this deviceCheck detectCapabilities()
RAVEN_EFFECT_INVALID_CONFIGOut-of-range or unknown parameter. Never silently clampedSee Filters for ranges
RAVEN_EFFECT_PROCESSING_FAILEDA frame could not be processed
RAVEN_EFFECT_PERMISSION_DENIEDAn asset or operation was refused
RAVEN_EFFECT_RESOURCE_LIMITToo many effects in one pipeline

Next steps