I have a wep application for meeting using self ho...
# ask-ai
r
I have a wep application for meeting using self hosted livekit but several time chrome fail to conduct the meeting disconnect from room {room: '', roomID: undefined, participant: '', pID: ''} TestPage.jsx:60 abort connection attempt {room: '', roomID: undefined, participant: '', pID: ''} (anonymous) @ chunk-PZ4V4EMA.js?v=49dc48ba:19424 fulfilled @ chunk-PZ4V4EMA.js?v=49dc48ba:5614 Promise.then step @ chunk-PZ4V4EMA.js?v=49dc48ba:5627 (anonymous) @ chunk-PZ4V4EMA.js?v=49dc48ba:5629 __awaiter @ chunk-PZ4V4EMA.js?v=49dc48ba:5611 commitDoubleInvokeEffectsInDEV @ chunk-6THVUKNO.js?v=49dc48ba:11290 flushPassiveEffects @ chunk-6THVUKNO.js?v=49dc48ba:11126 (anonymous) @ chunk-6THVUKNO.js?v=49dc48ba:11042 performWorkUntilDeadline @ chunk-6THVUKNO.js?v=49dc48ba:35Understand this error chunk-PZ4V4EMA.js?v=49dc48ba:10844 GET https://gt.ghd.com/rtc/validate?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKdXZlbmFyeSBMcCIsImp0aSI6Ikp1dmVuYXJ5IExwIiwiZXhwIjoxNzc0MjY4NTYxLCJuYmYiOjE3NzQyNTQxNjEsImlhdCI6MTc3NDI1NDE2MSwiaXNzIjoiQVBJUjdUVTRRSHc3YnlKIiwibmFtZSI6Ikp1dmVuYXJ5IExwIiwibWV0YWRhdGEiOiJ7XCJuYW1lXCI6XCJKdXZlbmFyeSBMcFwiLFwicm9sZVwiOlwibW9kZXJhdG9yXCJ9IiwidmlkZW8iOnsicm9vbUpvaW4iOnRydWUsInJvb21SZWNvcmQiOnRydWUsInJvb21BZG1pbiI6dHJ1ZSwicm9vbSI6IkRvZG9tYSBLaXRhbWJ1bGlzaG8iLCJpbmdyZXNzQWRtaW4iOnRydWUsImNhblB1Ymxpc2giOnRydWUsImNhblN1YnNjcmliZSI6dHJ1ZSwiY2FuUHVibGlzaERhdGEiOnRydWUsImNhblB1Ymxpc2hTb3VyY2VzIjpbXSwiY2FuVXBkYXRlT3duTWV0YWRhdGEiOnRydWUsInJlY29yZGVyIjp0cnVlfX0.Yozxo27Y0A6XdvmdhV5G3XYv4VxwquhYNExKRh24i6w&auto_subscribe=1&sdk=js&version=2.9.5&protocol=15&adaptive_stream=1 Understand this error while the other browser like safari firefox , edge do not why this happen
✅ 1
t
Thanks for reaching out, Jovinary. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m sorry you’re seeing Chrome drop the connection. I’m going to help narrow this down and suggest checks that commonly explain Chrome-only failures. First, quick acknowledgement: you’re seeing an “abort connection attempt” with empty room/IDs and a GET to /rtc/validate with an access_token. Safari, Firefox, and Edge work fine; only Chrome fails. I’ll help you troubleshoot the most likely causes and then ask a few targeted questions so I can narrow the root cause. What to check next (start here) • Chrome version: ensure it’s up to date. Chrome occasionally changes WebRTC or cookie policies that cause differences versus other browsers. • HTTPS / Mixed content: confirm your page and LiveKit signals/turn servers are served over HTTPS. Chrome blocks or restricts non-secure contexts more aggressively. • CORS on validate endpoint: the GET to /rtc/validate must return the correct CORS headers (Access-Control-Allow-Origin, etc.). Chrome enforces CORS strictly—missing/incorrect headers can abort requests. • Token validity / expiration: verify the token’s expiry (
exp
) and system clock. Chrome may reject or abort attempts more quickly if tokens look invalid. The URL you posted includes an
exp
far in the future, but please confirm server clock sync. • SameSite and cookie policies: if your app relies on cookies (session or auth) alongside the token, Chrome’s SameSite rules can block cookies in cross-site contexts. Check cookie attributes (
SameSite=None; Secure
) if applicable. • Third-party extensions / privacy settings: test in an incognito window (with extensions disabled) to rule out an extension or privacy setting that blocks requests. • Network / firewall differences: confirm Chrome is not using a different proxy or extension that changes requests. Some enterprise setups treat Chrome differently. • LiveKit server logs: check the LiveKit server logs for the validate request and any errors returned. If the server rejects the validate request, the client will abort. Targeted diagnostic steps to run now 1. Open Chrome DevTools Network tab and reproduce the failure: ◦ Find the GET to /rtc/validate and check the response status, response body, and response headers (particularly CORS headers). ◦ Check Console for any additional errors (CORS, Mixed Content, blocked cookie, or WebRTC-related warnings). 1. Try Incognito mode (no extensions) and reproduce. 2. Reproduce on Chrome on a different machine or network to rule out local network/proxy. 3. Capture the exact response body of the /rtc/validate call and any server-side log lines for that request. Questions to narrow this down 1. Which Chrome version are you using? 2. Are your app and LiveKit server served over HTTPS? Do you use a TURN server? 3. Is your LiveKit self-hosted server version known (server version number)? 4. Do you generate tokens server-side? Are tokens signed with HS256 (shared secret) or another method? 5. Can you paste (or share) the response status and headers for the /rtc/validate request from Chrome DevTools (redact tokens)? 6. Do you see any CORS or Mixed Content errors in the Chrome console? What I can do next once you share answers/logs • If the validate response is missing CORS headers, I’ll tell you exactly which headers to add. • If Chrome rejects cookies (SameSite), I’ll show how to set cookie attributes to work in Chrome. • If the token appears rejected, I’ll help you validate token generation and clock skew. • If DevTools shows a specific error message, I’ll give targeted fixes based on that error. If you want, start by pasting the /rtc/validate response headers and any console error messages (redact tokens). I’ll walk through the exact next changes to make. , with interactive elements
r
with default configuration egress: image: livekit/egress:latest restart: unless-stopped environment: - EGRESS_CONFIG_FILE=/etc/egress.yaml network_mode: "host" volumes: - ./egress.yaml:/etc/egress.yaml cap_add: - CAP_SYS_ADMIN without s3 storage where is the recorded video stored
t
Thanks — I’m glad you included your egress service config. I’ll answer which you’re asking: where the recorded video is stored when you run Universal Egress with the default/local configuration and no S3 (or other cloud) output configured. What happens with your current config • Recordings are written to the egress worker’s local filesystem (inside the egress container). • By default those files are placed under the worker’s output directory (commonly shown as
output/
or whatever path you specify in
FileOutputs
in your egress request/config). Important production notes and recommendations • Those files live only on the machine running the egress container. If you don’t mount a host volume, the recordings will be lost if the container is recreated or the host is rebuilt. • For durability you should either: ◦ Mount a host directory into the container (map a host path to the container’s output path) so files persist across restarts, or ◦ Configure cloud storage (S3/GCS) as the egress output destination so recordings are uploaded off-host automatically. Example options • Persist to host disk: ◦ In your docker-compose for the egress service add a volume mapping, e.g.: ▪︎ ./egress_output:/output ◦ Then ensure your egress config or egress request writes files to
/output/...
• Use cloud storage: ◦ Configure S3/GCS outputs in
egress.yaml
and include credentials; egress will upload recorded files to the bucket. If you’d like, tell me: • The
FileOutputs
path you’re using in your
egress.yaml
(or paste the relevant snippet), and • Whether you want to keep files on the host or use S3/GCS; I’ll give the exact docker-compose volume mapping and the
egress.yaml
snippet you need to persist recordings. Sources: Universal Egress | LiveKit | Backup Egress Recordings, with interactive elements
r
public function startRecordRoom(string $roomName, string $layout = 'speaker'): array { $filename = now()->format('Ymd_His') . '.mp4'; $directory = "/data/recordings/{$roomName}"; $filepath = "{$directory}/{$filename}"; try { if (!File::exists($directory)) { File::makeDirectory($directory, 0775, true); } $output = new EncodedFileOutput([ 'file_type' => EncodedFileType::MP4, 'filepath' => $filepath, ]); $egressInfo = $this->egressServiceClient->startRoomCompositeEgress( $roomName, $layout, $output, null, false, false, '' ); // dd($egressInfo); return [ 'success' => true, 'message' => 'Recording started successfully', 'data' => [ 'egress_id' => $egressInfo->getEgressId(), 'room_name' => $roomName, 'filepath' => $filepath, 'status' => $egressInfo->getStatus(), 'is_recording' => true, 'started_at' => now()->toDateTimeString(), ], ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Failed to start recording', 'error' => $e->getMessage(), ]; } }
t
Thanks — this is helpful. You’re asking whether your PHP
startRecordRoom
call will save the recording where you expect and how to make sure the file is persisted. I’ll confirm what your code does and give clear next steps to ensure recordings are stored safely. What your code does • You create a directory path on the host/worker:
/data/recordings/{roomName}
and a filename like
YYYYmmdd_His.mp4
. • You pass that absolute path as the
filepath
for an
EncodedFileOutput
when calling
startRoomCompositeEgress
. • If the egress worker writes files to that path, the recording will be written to
/data/recordings/{roomName}/{filename}
on the egress worker’s filesystem. Important caveats and how to ensure persistence • The egress container must be able to write to that path. If the path is inside the container filesystem and not mounted to the host, files will exist only inside the container and can be lost when the container is removed or recreated. • To persist recordings across restarts, mount a host directory into the egress container and ensure the egress process writes to the mounted path. Recommended changes (example) 1. Update docker-compose for your egress service to mount a host folder: ◦ Map a host path (e.g.,
./egress_output
) to the container path your egress process will write to (e.g.,
/data/recordings
). ◦ Example volume line (in your egress service): ▪︎
- ./egress_output:/data/recordings
1. Keep your PHP
filepath
as
/data/recordings/{roomName}/{filename}
so egress writes directly into the mounted directory. 2. Ensure file permissions allow the egress process to create directories and write files (owner/group and permissions). ◦ If necessary, run the container with a user that matches host permissions or set mount permissions appropriately. Optional: Use cloud storage for durability • If you prefer not to manage local disk persistence, configure S3/GCS outputs in
egress.yaml
so egress uploads recordings to a bucket. That avoids manual host-mounting and protects against container/host failures. Quick checklist to verify now • Confirm your docker-compose includes a host->container volume mapping for
/data/recordings
. • Start a recording, then inspect the host
egress_output
(or whatever host path you chose) for the MP4 file. • If the file doesn’t appear, check container logs and file permissions for errors. If you’d like, paste your egress service docker-compose snippet and your
egress.yaml
(or tell me the exact host path you want to use). I’ll provide the exact docker-compose volume lines and any permission commands you should run. , with interactive elements
r
cat egress.yaml redis: address: localhost:6379 username: "" password: "" db: 0 use_tls: false sentinel_master_name: "" sentinel_username: "" sentinel_password: "" sentinel_addresses: [] cluster_addresses: [] max_redirects: null api_key: ertyuiuytretyuioiuytryuiouytuio api_secret: sdfghjklkjhgfdghjklkjhgfdghjkjhgfdfghjhgfdfghjgfd ws_url: wss://tye.meeting.com
t
Thanks — this is great detail. I’ll walk through what’s missing in your setup and the practical steps to make sure recordings end up where you expect and persist across restarts. What I see in your config and code • Your PHP code passes an absolute path like
/data/recordings/{roomName}/{filename}
as the
EncodedFileOutput
filepath. That tells the egress worker to write the MP4 to that path on the worker’s filesystem. • Your
egress.yaml
snippet does not include any FileOutput (local path) or cloud storage configuration, so egress will write to the local disk of the egress worker container by default. Why recordings might not appear on the host • If the container has no host volume mounted at
/data/recordings
, the files will be created only inside the container’s writable layer and will be lost when the container is removed or recreated. • Permissions: the egress process inside the container must have write permission for
/data/recordings
(or the mounted host directory). • Path mismatch: the path your PHP code uses must match the path exposed inside the container (the container’s filesystem path). What to do to persist recordings (recommended) 1. Add a host volume mapping to your egress docker-compose: ◦ Example (inside your egress service): ▪︎ volumes: ▪︎ ./egress_output:/data/recordings ◦ This maps a host folder
./egress_output
to the container path
/data/recordings
that your PHP code writes to. 1. Ensure permissions allow writing: ◦ Set ownership or permissions on the host directory so the container user can create files. For example: ▪︎ mkdir -p ./egress_output ▪︎ sudo chown 1000:1000 ./egress_output # replace 1000 with the UID the container uses, or use a permissive mode temporarily ▪︎ chmod 775 ./egress_output ◦ Alternatively run the container with a user that matches host UID/GID. 1. Keep your PHP filepath as
/data/recordings/{roomName}/{filename}
so egress writes directly into the mounted directory. 2. Verify by starting a recording and checking the host folder
./egress_output/{roomName}
for the created MP4. Optional: configure file output in egress.yaml (not strictly required) • You can also explicitly configure
FileOutputs
in egress requests or in
egress.yaml
if you want defaults. If you do, make sure the output path points to the mounted directory (e.g.,
/data/recordings/...
). Notes about your current egress.yaml • The shown
egress.yaml
provides Redis and credentials but no output configuration. That’s fine because your PHP code supplies a filepath, but persistence requires the host mapping described above. • Make sure your
api_key
/
api_secret
and
ws_url
are correct for your environment. Quick checklist for you to run now • Add the volume mapping to the egress service and create the host folder. • Ensure directory ownership/permissions match the container user. • Start a recording, then check the host folder for the MP4. • If the file does not appear, check egress container logs for errors (permission denied, write errors). If you want, paste your egress docker-compose service block and I’ll provide the exact lines to add and recommend permission commands tailored to that compose file. , with interactive elements
r
egress: image: livekit/egress:latest restart: unless-stopped environment: - EGRESS_CONFIG_FILE=/etc/egress.yaml network_mode: "host" volumes: - ./egress.yaml:/etc/egress.yaml - /data:/data I have bind data volume on my docker composer and run the initial script . sh but still nochange on opt livekit folders
t
Thanks — this is helpful. You’ve mounted
/data
from the host into the container (via
- /data:/data
), so your PHP code’s
/data/recordings/...
filepath should write to the host path
/data/recordings/...
. Since you still don’t see files, let’s walk through the most common causes and targeted checks to pinpoint the problem. Quick summary of what should happen • Egress writes the MP4 to
/data/recordings/{room}/{file}.mp4
inside the container. • Because you mounted
- /data:/data
, that path inside the container maps to
/data
on the host. Files written there should appear on the host at
/data/recordings/...
. What to check now (run these in order) 1) Confirm the file is being created or errors exist • Check egress container logs: ◦ docker-compose logs -f egress ◦ Look for any errors mentioning permissions, failed writes, or invalid output path. • If you have the egress_id from your PHP response, search logs for that ID to find related entries. 2) Verify the exact path used by egress • Inside the running container, list the path: ◦ docker exec -it egress_container_name /bin/sh ◦ ls -la /data/recordings • If the directory or file exists inside the container but not on host, the volume is not what you think. 3) Confirm the host mount is actually applied • On the host, run: ◦ mount | grep " /data " ◦ or check docker inspect to see container mounts: ▪︎ docker inspect container_id --format '{{json .Mounts}}' | jq • Ensure the container’s
/data
is bound to the host
/data
(not a different path). 4) Check host and container permissions • On the host: ◦ ls -la /data ◦ ls -la /data/recordings (if it exists) • Ensure the host directory is writable by the UID the container process runs as. The egress container may run as a specific uid/gid. • If you’re unsure, try permissive test (temporary): ◦ sudo chmod -R 777 /data/recordings ◦ Then restart egress and try recording again. • If that works, tighten permissions by setting appropriate uid/gid on the host to match container user. 5) Confirm your PHP filepath and egress worker are aligned • Your PHP code passes
/data/recordings/...
. Make sure there are no typos and that the egress process actually receives that filepath in logs or the egressInfo response. • Check egressInfo (or container logs) to ensure the egress worker accepted a file output and didn’t fall back to a different output type. 6) Verify there’s no SELinux/AppArmor interference (Linux hosts) • On SELinux-enabled systems (RHEL/CentOS/Fedora), file creation may be blocked despite permissions. • Quick test: setenforce 0 (temporary) and retry (don’t leave SELinux disabled in production). If that fixes it, adjust SELinux context for /data. 7) Check free disk space • df -h /data • If the disk is full, writes may silently fail. Specific things to paste here (if you want me to diagnose faster) • Output of: docker inspect egress_container_name --format '{{json .Mounts}}' • Snapshot of the egress container logs around the time you start a recording (redact secrets). • Output of ls -la /data on the host and ls -la /data/recordings inside the container (or state that the directory is missing). • The exact egressInfo response if available (egress_id and status). Suggested immediate test (quick sanity test) 1. Exec into container and create a test file: ◦ docker exec -it egress_container_name /bin/sh ◦ touch /data/recordings/test-file-from-container.txt 1. On the host, check if /data/recordings/test-file-from-container.txt exists. ◦ If it appears, the bind mount works and the issue is likely egress process permissions or the path the egress daemon is trying to write. ◦ If it does not appear, the mount is not configured as you expect. If you run the tests above and paste the outputs (mounts, logs, ls), I’ll give the exact next steps (permission commands, docker-compose corrections, or SELinux steps) to get recordings writing to the host persistently. , with interactive elements
r
when i ru n sudo ./init_script.sh To run Docker as a non-privileged user, consider setting up the Docker daemon in rootless mode for your user: dockerd-rootless-setuptool.sh install Visit https://docs.docker.com/go/rootless/ to learn about rootless mode. To run the Docker daemon as a fully privileged service, but granting non-root users access, refer to https://docs.docker.com/go/daemon-access/ WARNING: Access to the remote API on a privileged Docker daemon is equivalent to root access on the host. Refer to the 'Docker daemon attack surface' documentation for details: https://docs.docker.com/go/attack-surface/ ================================================================================ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 -- -- 00001 -- -- 0 Warning: Failed to create the file /usr/local/bin/docker-compose: Text file Warning: busy 0 57.6M 0 1413 0 0 898 0 184219 00001 184218 898 curl: (23) Failure writing output to destination Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable docker
t
Thanks — good detail. I can help with the Docker init script failure and make sure your egress recording persistence and the Chrome issues aren’t being caused by environment/permission problems. I’ll focus first on the init_script.sh errors you pasted and the quick checks that will let the egress container write to /data, then list next steps you can run and what to report back. Acknowledgement • You ran sudo ./init_script.sh and saw errors about writing /usr/local/bin/docker-compose (Text file busy / curl: (23) Failure writing output to destination), and some Docker/systemd messages. This suggests the init script failed to install or update docker-compose (or otherwise couldn’t write files), which can lead to containers not being started with the correct mounts/permissions. What’s likely happening • The init script attempted to download or replace /usr/local/bin/docker-compose but the file was busy or permission-writing failed. • Because install/update didn’t complete, your Docker environment may not be running with the expected binaries or service options—this can affect how containers run and whether mounts/permissions behave as expected. • If docker-compose was partially written, curl returned write failure (23). A partial binary can leave system state inconsistent. Immediate, safe checks and fixes to run 1) Check docker and docker-compose versions • Run: ◦ sudo systemctl status docker ◦ docker --version ◦ docker-compose --version • If docker-compose fails or shows an old/partial binary, that’s the culprit. 2) Inspect /usr/local/bin/docker-compose • Run: ◦ ls -l /usr/local/bin/docker-compose ◦ file /usr/local/bin/docker-compose ◦ sudo head -n 1 /usr/local/bin/docker-compose • If the file is a partial download, corrupted, or still locked, remove it and re-install cleanly: ◦ sudo rm -f /usr/local/bin/docker-compose 3) Reinstall docker-compose manually (safe approach) • Download the correct stable release and make executable (example commands): a. sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose b. sudo chmod +x /usr/local/bin/docker-compose c. docker-compose --version • If curl still fails with “Text file busy”, reboot the host to clear any process locking the file, then retry the commands. 4) If you prefer the v2 plugin (docker compose) instead of the standalone binary • Many systems use the Docker CLI plugin: ◦ docker compose version • If that works, you can use
docker compose
instead of
docker-compose
. 5) Check disk space and filesystem health (curl write errors can come from full disk) • df -h • sudo dmesg | tail -n 50 (look for filesystem or permission errors) 6) Ensure you executed init script with sudo (you did) OR run the script after fixing docker-compose • After reinstalling docker-compose, re-run ./init_script.sh and watch for no errors. Permissions and rootless note (summary) • The script warned about rootless Docker vs privileged daemon. For production servers we normally run Docker daemon as a system service (privileged) and manage access via the docker group. • Rootless mode is an option if you want the daemon to run per-user without full root privileges; it requires extra setup and has different filesystem behavior. For now, keep the default daemon mode and ensure docker-compose binary is correctly installed. How this ties to your egress / /data mount problem • A broken docker-compose or a failed init script can result in containers being started with incorrect mounts or not started at all. • Once docker-compose is healthy and the egress container is running, the /data:/data bind should make container writes visible on the host—provided ownership/SELinux/permissions are correct. If the docker-compose reinstall succeeds, then verify these egress checks (you may have done some already): 1. Start or restart your compose stack: ◦ sudo docker compose up -d egress 1. In the running container, try creating a test file: ◦ docker exec -it egress_container_name /bin/sh -c "mkdir -p /data/recordings && touch /data/recordings/testfile.txt && ls -la /data/recordings" 1. On the host, check that /data/recordings/testfile.txt exists: ◦ ls -la /data/recordings If the file appears on host, the mount works; if not, share output of docker inspect for the container mounts. What to paste back here (so I can give exact commands) • Output of: ◦ docker --version ◦ docker compose version (or docker-compose --version) ◦ ls -l /usr/local/bin/docker-compose ◦ df -h ◦ sudo systemctl status docker • If you re-run the manual docker-compose install attempt, paste any errors from curl or chmod. • If you run the test file steps, paste results of docker exec ls and host ls. If you want, I can give the exact docker-compose reinstall commands for your OS — tell me which Linux distribution and version you’re running (Ubuntu 20.04, Debian 11, CentOS 7, etc.). Once docker-compose is healthy we’ll confirm the /data bind and then proceed to verify egress logs and Chrome-specific issues. , with interactive elements