Skip to content

Troubleshooting

Start with the layer closest to the failure:

Terminal window
docker compose ps
docker compose logs --tail=200 control-plane
curl -i http://localhost:8090/health

The control plane started without TOMO_STREAM_API_KEY or TOMO_STREAM_API_KEYS.

  1. Confirm the value exists in .env.
  2. Recreate the service: docker compose up -d --force-recreate control-plane.
  3. Never send the API key from browser code.

The x-api-key header does not match the configured value. Check for copied quotes, whitespace or a shell variable exported in a different terminal.

If session creation reports a missing image, confirm the local tags:

Terminal window
docker image inspect tomo-streaming-control-plane:local
docker image inspect tomo-av-stream-server:local

Then confirm .env uses those exact names. GHCR preview images are not published yet.

The control plane needs /var/run/docker.sock. Confirm it is mounted and that the Docker daemon is running:

Terminal window
test -S /var/run/docker.sock
docker info

Treat the socket as privileged infrastructure; do not expose the control-plane container to untrusted workloads.

Terminal window
ls -l /dev/video0
v4l2-ctl --list-devices

Verify that CAMERA_DEVICE_HOST points to the same device and that Docker can read it. Try "captureAudio": false first to isolate video from audio configuration.

  • Confirm the requested display with echo "$DISPLAY".
  • Verify the X11 socket exists under /tmp/.X11-unix.
  • Ensure the capture process is authorized to read that display.
  • Start without audio, then configure the PulseAudio socket separately.

That state is correct until a player joins with its temporary room and access token. status describes the runtime lifecycle; runtime.activity describes occupancy.

  1. Confirm the client uses wss:// when the API uses HTTPS.
  2. Verify WebSocket upgrade routing for /signaling.
  3. Test from the same network before adding TURN.
  4. Configure TURN for mobile, corporate or symmetric-NAT networks.
  5. Check that the player uses connection.accessToken, not the server API key.

Video works locally but not over the internet

Section titled “Video works locally but not over the internet”

This usually indicates ICE/NAT reachability rather than an encoder problem. Configure PUBLIC_IP and TURN, then test from a mobile network. Monitor TURN bandwidth separately because relayed media carries an infrastructure cost.

Include:

  • repository commit and worker OS;
  • Docker and Compose versions;
  • source type and sanitized session configuration;
  • control-plane logs with all tokens removed;
  • whether health, discovery and runtime creation passed.

Open the issue in the repository that owns the failing layer rather than in Tomo Social.