Troubleshooting
Start with the layer closest to the failure:
docker compose psdocker compose logs --tail=200 control-planecurl -i http://localhost:8090/healthapi_disabled
Section titled “api_disabled”The control plane started without TOMO_STREAM_API_KEY or TOMO_STREAM_API_KEYS.
- Confirm the value exists in
.env. - Recreate the service:
docker compose up -d --force-recreate control-plane. - Never send the API key from browser code.
invalid_api_key
Section titled “invalid_api_key”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.
Runtime image not found
Section titled “Runtime image not found”If session creation reports a missing image, confirm the local tags:
docker image inspect tomo-streaming-control-plane:localdocker image inspect tomo-av-stream-server:localThen confirm .env uses those exact names. GHCR preview images are not published yet.
Cannot access Docker
Section titled “Cannot access Docker”The control plane needs /var/run/docker.sock. Confirm it is mounted and that the Docker daemon is running:
test -S /var/run/docker.sockdocker infoTreat the socket as privileged infrastructure; do not expose the control-plane container to untrusted workloads.
Camera session fails immediately
Section titled “Camera session fails immediately”ls -l /dev/video0v4l2-ctl --list-devicesVerify 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.
Desktop is blank
Section titled “Desktop is blank”- 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.
Session is running but shows empty
Section titled “Session is running but shows empty”That state is correct until a player joins with its temporary room and access token. status describes the runtime lifecycle; runtime.activity describes occupancy.
Player cannot connect
Section titled “Player cannot connect”- Confirm the client uses
wss://when the API uses HTTPS. - Verify WebSocket upgrade routing for
/signaling. - Test from the same network before adding TURN.
- Configure TURN for mobile, corporate or symmetric-NAT networks.
- 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.
Report a reproducible issue
Section titled “Report a reproducible issue”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.