what does this error mean? {“message”: “service.st...
# ask-ai
r
what does this error mean? {“message”: “service.stop_recording failed; spawning finalizer to reconcile DB. egress_id=EG_FS6tXE2HniGB error=401, message=‘Attempt to decode JSON with unexpected mimetype: text/plain; charset=utf-8’, url=‘https://replify-develop-7h0cuhf3.livekit.cloud/twirp/livekit.Egress/StopEgress’“, “level”: “WARNING”, “logger”: “app.services.recording_orchestrator”, “timestamp”: 1779981174.6551542, “conversation_id”: “f5c65894-6638-45e6-84ef-f546eb5deee7”, “service”: “phone-worker”, “room_name”: “inbound-call-_+15052491219_UdBQtxnsk556”, “twilio_call_sid”: “CAc1467b82f19c805b7e97b5e5e10b079f”, “call_sid”: “SCL_kQ9xvaCPuLDa”, “to_number”: “+15052073387”, “from_number”: “+15052491219”, “agent_id”: “17af1189-350c-426f-a965-86018f3ba959”, “contact_id”: “c3fa21db-6421-471e-be02-a332bc2491ba”, “module”: “recording_orchestrator”, “function”: “stop_recording”, “line”: 408}
t
Thanks for reaching out, luisa. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m looking at the log line for
service.stop_recording
that shows a 401 and a JSON decode error. I’ll explain what it means and what to check next. What the error means • The StopEgress RPC call to https://…/twirp/livekit.Egress/StopEgress returned HTTP 401 (Unauthorized). • The client expected a JSON response but the server returned plain text (
text/plain; charset=utf-8
), so the client failed to decode it and logged the MIME-type mismatch. • In short: the request was rejected for authorization, and the error response wasn’t JSON so the client couldn’t parse it cleanly. What to check next • Verify the token used for the StopEgress call: ◦ Confirm the API key/secret pair used to sign the JWT matches the LiveKit project for that endpoint. ◦ Decode the JWT and check `nbf`/`exp` (not-before/expiry) and
iss
to ensure it’s for the correct project and not expired or not-yet-valid. • Check for clock skew between the token issuer and the LiveKit server (can cause `nbf`/`exp` failures). • Confirm you’re calling the correct LiveKit host/URL for that environment (dev vs prod) so keys match the project. • If StopEgress is sent from a service, ensure it’s using current credentials (not a cached or rotated/invalid secret). If you want, send: • the egress_id (EG_FS6tXE2HniGB) and the token or decoded token payload (don’t share secrets) — I can point to which claim likely caused the 401, • or tell me whether the stop request is issued from a server process that recently had its credentials rotated. I can walk through decoding the token and the exact claims to inspect if you share the decoded JWT payload. Sources: Troubleshooting 401 Unauthorized and Token Errors | LiveKit, with interactive elements
r
it happened just 2x randomly now it works. what’s the isssues
t
Thanks — glad it’s working now. Here’s why those two transient errors most likely happened and what to watch for. What likely caused the intermittent 401 + MIME mismatch • A brief authentication failure: the StopEgress request was rejected (401), and the server returned a plain-text error instead of JSON so the client couldn’t decode it. • Common transient triggers: ◦ A token that was just expired or not-yet-valid (small timing window). ◦ Short-lived clock skew between the token issuer and the LiveKit host. ◦ A momentary use of the wrong/rotated API key or secret (e.g., cached credential briefly invalid). ◦ A transient networking/proxy response that returned a plain-text error page. Why it can happen only a couple of times • Tokens or clocks can cause a single failed request until the next token refresh or automatic retry succeeds. • Short credential rotation or a transient proxy/edge response can affect only a few requests and then clear. Quick checks to prevent recurrence • Decode a sample token used by the service and confirm `nbf`/`exp` and
iss
are correct. • Ensure the service refreshes tokens and isn’t using a cached/rotated secret. • Verify system clocks on token issuers and callers are in sync (NTP). • If retries are not in place, consider retrying StopEgress on 401 once (with short backoff) since it can be transient. If you’d like, I can: • Help inspect a decoded JWT payload (not the secret) to point to the problematic claim, or • Review whether your service is using cached credentials or needs a retry on transient auth failures. Which would you prefer? , with interactive elements
r
it never happened before I have never seen this issue
t
Thanks — I hear you: it only happened twice and never before, so you want a concise explanation and reassurance. Short answer • Those two events were most likely transient authentication failures: the StopEgress call was rejected with HTTP 401 and returned plain-text error text (hence the JSON MIME decode error). Because the condition cleared, subsequent requests succeeded. Most likely transient causes • A token was briefly expired or not-yet-valid (small timing window). • Short-lived clock skew between the issuer and the LiveKit host. • A momentary use of a rotated/invalid cached credential. • A transient proxy/edge or network response that returned a plain-text error page. What to do (quick checks) • Confirm service clocks are synced (NTP). • Ensure tokens are refreshed and you’re not reusing a stale cached secret. • Decode one sample JWT (no secrets) and verify `nbf`/`exp` and
iss
. • Add a single retry with short backoff for StopEgress on 401 if you don’t already have retries. If you want, I can: • Inspect a decoded JWT payload (don’t share private keys) to point out problematic claims, or • Check whether your service may have briefly used rotated credentials. Which would you like me to do? , with interactive elements
r
is this true? LiveKit JWT validation is time-sensitive; NTP drift on the container host can cause intermittent 401s (a known LiveKit issue pattern)
t
Yes — that’s true. LiveKit JWT validation checks time-based claims (
nbf
,
exp
), so token acceptance is time-sensitive. If the container host clock drifts (NTP not synced) a token can appear expired or not-yet-valid and produce intermittent 401s. What to do: • Ensure hosts issuing tokens and the LiveKit caller/server have synchronized clocks (enable NTP). • Verify token TTLs aren’t too short. • Add a short retry on 401 for transient auth failures. • If you want, share a decoded JWT payload (no secrets) and I’ll point out any timing claims that look problematic., with interactive elements
r
what’s NTP and nbf
t
Good question — short definitions and why they matter. • NTP (Network Time Protocol): a protocol that synchronizes a computer’s clock to an accurate time source (usually internet time servers). If a host’s clock drifts even a few seconds, time-sensitive checks can fail. •
nbf
(JWT "not before"): a claim inside a JWT that says the token is not valid until the specified timestamp. If the server’s clock is earlier than the
nbf
time, the token will be rejected as “not yet valid.” Why this matters for LiveKit • LiveKit checks JWT time claims (
nbf
,
exp
). If clocks aren’t synced (NTP not running) or a token’s `nbf`/`exp` is off, requests can intermittently return 401 Unauthorized. Would you like me to: • Walk you through checking NTP on your hosts, or • Inspect a decoded JWT payload (no secrets) to check `nbf`/`exp` values?, with interactive elements