Hi, we have setup our livekit instance in k8s, sip...
# ask-ai
l
Hi, we have setup our livekit instance in k8s, sip.livekitserver,egress voiceagent calls are working but the call recordings are not happening ], "recording": { "egress_id": null, "filepath": null } } im seeing this errors 2026-03-05 100416 [ERROR] src.services.egress_service: [ERROR]: TwirpError(code=invalid_argument, message=twirp error unknown: request has missing or invalid field: token or api key/secret, status=400)
t
Thanks for reaching out, Sathish. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — that error message makes the issue clear: the Egress service cannot authenticate with your LiveKit server, so recordings never start. I’ll walk you through the minimal checks and fixes to get egress recording working. What I’m responding to: the Twirp error
request has missing or invalid field: token or api key/secret
and the egress JSON showing
egress_id: null
and
filepath: null
. Quick checklist (do these in order): 1) Ensure Egress has API credentials • Add the API key and secret as environment variables in the Egress container: ◦ LIVEKIT_API_KEY = your-api-key ◦ LIVEKIT_API_SECRET = your-api-secret ◦ LIVEKIT_URL = the LiveKit server URL (example: ws://livekit:7880 or your external URL) • Restart the Egress pod after adding/updating these values so they are picked up. 2) Confirm values are correct and not mistyped • Double-check there are no extra quotes, hidden characters, or typos in the key/secret names or values. • If you rotate keys, make sure Egress uses the current secret. 3) If you use JWT token auth for egress instead of API key/secret • Verify the token is signed with the correct API secret. • Ensure the token includes necessary permissions for recording (room recording/egress). • Check
exp
and
nbf
are valid and the token is not expired/not-yet-valid. • Decode the token (e.g., via jwt.io or
echo "<token>" | cut -d'.' -f2 | base64 -d | jq
) to inspect claims. 4) Verify Egress can reach the LiveKit server • Exec into any pod (or use a test pod) and curl the LiveKit URL to confirm connectivity: ◦ curl -v http://livekit:7880 • Ensure the Twirp endpoints are reachable from the Egress pod. 5) If you’re using SIP Dispatch Rules / auto-egress • Ensure your dispatch rule includes
room_config.egress
(so rooms created by SIP have egress recording configured). • Example: room_config with egress outputs (S3, file, etc.) must be present for auto-egress to start recordings. 6) Inspect logs after changes • Restart Egress and check logs: ◦ kubectl logs -f <egress-pod-name> • Successful auth will remove the Twirp invalid_argument error; otherwise logs will show further clues. What success looks like • Egress logs show a successful initialization/auth handshake. • When a call starts, the room’s egress fields populate with
egress_id
and
filepath
instead of null. If you want, tell me: • How you currently provide credentials to the Egress pod (env vars, secret mount, or token). • The LiveKit service URL you set in the Egress deployment (cluster-internal or external). • Whether you use API key/secret or JWT tokens for Egress auth. With that I can give the exact Kubernetes YAML snippet or token validation steps to apply to your deployment. Sources: Server-side | livekit/livekit_composite | DeepWiki | server-sdk-js | livekit/livekit_composite | DeepWiki | sip | livekit/livekit_composite | DeepWiki | Troubleshooting 401 Unauthorized and Token Errors | LiveKit | Universal Egress
l
can u give me deployment.yaml for the egress for k8s deployment
t
Thanks — I’ll give you a ready-to-use Kubernetes Deployment + Service + Secret example for the LiveKit Egress service you can adapt to your cluster. This includes the necessary env vars (API key/secret, LIVEKIT_URL, Redis) so the Egress service can authenticate and receive jobs. Please replace placeholder values (domain, secret data, Redis URI) with your real values before applying. 1) Secret (store API key & secret)
Copy code
apiVersion: v1
kind: Secret
metadata:
  name: livekit-secrets
  namespace: livekit
type: Opaque
data:
  api-key: BASE64_ENCODED_API_KEY
  api-secret: BASE64_ENCODED_API_SECRET
2) Deployment for LiveKit Egress
Copy code
apiVersion: apps/v1
kind: Deployment
metadata:
  name: livekit-egress
  namespace: livekit
  labels:
    app: livekit-egress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: livekit-egress
  template:
    metadata:
      labels:
        app: livekit-egress
    spec:
      containers:
        - name: egress
          image: livekit/egress:latest
          ports:
            - containerPort: 7980
              name: http
          env:
            - name: LIVEKIT_URL
              value: "<wss://your-livekit-domain.com>"   # or ws:// for internal cluster URL
            - name: LIVEKIT_API_KEY
              valueFrom:
                secretKeyRef:
                  name: livekit-secrets
                  key: api-key
            - name: LIVEKIT_API_SECRET
              valueFrom:
                secretKeyRef:
                  name: livekit-secrets
                  key: api-secret
            - name: REDIS_URI
              value: "<redis://redis.livekit.svc.cluster.local:6379>" # update as needed
            - name: GST_DEBUG
              value: "3" # optional for debugging gstreamer
            - name: LIVEKIT_REGION
              value: "us-west" # optional
          readinessProbe:
            httpGet:
              path: /health
              port: 7980
            initialDelaySeconds: 10
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 7980
            initialDelaySeconds: 30
            periodSeconds: 10
          resources:
            requests:
              cpu: "500m"
              memory: "512Mi"
            limits:
              cpu: "2"
              memory: "2Gi"
3) Cluster Service (optional — for internal access / health checks)
Copy code
apiVersion: v1
kind: Service
metadata:
  name: livekit-egress
  namespace: livekit
  labels:
    app: livekit-egress
spec:
  selector:
    app: livekit-egress
  ports:
    - protocol: TCP
      port: 7980
      targetPort: http
      name: http
Notes and quick checks • LIVEKIT_URL must point to your LiveKit server (internal cluster address or public WSS). Egress must be able to reach this URL. • LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be correct and accessible by the Egress pod — incorrect/missing credentials cause the Twirp invalid_argument error you saw. • REDIS_URI: Egress uses Redis to receive job requests; confirm Redis is reachable from the pod. • Restart the Deployment after you create/update the Secret so the pod picks up new values: kubectl rollout restart deployment/livekit-egress -n livekit • Monitor logs for auth success or remaining errors: kubectl logs -f deploy/livekit-egress -n livekit If you’d like, I can: • Provide a variant that uses a mounted file Secret instead of env vars. • Show the exact kubectl commands to create the Secret (including base64 encode commands). • Tailor resource requests/limits and replica count for production load. Which of those would help you next? Sources: Universal Egress | Universal Egress | livekit/livekit_composite | DeepWiki | sip | livekit/livekit_composite | DeepWiki | Backup Egress Recordings