Why does Jigasi crash with pthread_create failed (EAGAIN)?

Short answer

pthread_create failed (EAGAIN) means Jigasi cannot create a native thread, which can reflect memory or task limits rather than a full Java heap. Upgrade older Whisper installations to a Jigasi version containing PR #619 and fix failing speech backend connections. Keep heap and container limits separate, and explicitly forward JIGASI_MAX_MEMORY in Docker's transcriber service. The Vosk failure-path report remains unresolved as of 2026-10-06. [S1][S2][S3][S6]

Symptoms

Captions stop and Jigasi can no longer start threads. Issue #615 contains these exact log fragments, including a WebSocket thread name: [S1]

Text
Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN)
Failed to start the native thread for java.lang.Thread "WebSocket@1015685120-8400"
java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached

One contributor reported roughly 170 MB of heap use but 25,000 threads after failed Whisper connections. That is a thread-growth report, not evidence that every installation needs a larger heap. A separate heap-exhaustion message is java.lang.OutOfMemoryError: Java heap space. [S1][S7]

Cause

EAGAIN can indicate insufficient resources or a thread/process limit. Native stacks and other process memory sit outside the Java heap. A container can run out of resources while its heap remains small. Compare threads, resident memory and heap usage together. [S5][S6][S7]

Jigasi’s launcher defaults JIGASI_MAX_MEMORY to 3072m and passes it through -Xmx, about 3 GiB of maximum heap. Stock stable-11248/transcriber.yml does not forward this variable. Putting it only in .env therefore does not override the launcher. [S3][S4]

The maintainer recommended at least 3.5 GB for the container around the default heap, rather than a 2 GB container limit. This is a starting allocation, not a guaranteed capacity. In the failure report, the maintainer also identified repeated Whisper 403 errors and asked the operator to fix them. [S1]

Whisper PR #619 merged December 9, 2025. It stops failed WebSocket clients, limits connection attempts and adds a timeout. Its code is present in released Jigasi 1.1-415-g2750d54-1. Later Vosk reports in #615 remain unresolved. PR #650 targets graceful Whisper shutdown and transcript completion, is still open, and is not a released fix for this issue. [S1][S2][S8]

Fix

  1. Docker stable-11248: capture measurements before restarting. Include your existing overlays in this helper. The stock transcriber has one Java process; these commands select it. UID 1000 matches the rootless process. [S3][S5][S9]

    Terminal
    dc() {
        docker compose -f docker-compose.yml -f transcriber.yml "$@"
    }
    dc logs --tail=200 transcriber
    dc exec -T --user 1000:1000 transcriber sh -lc '
        pid=$(pgrep -o -x java)
        test -n "$pid" || exit 1
        grep -E "^(Threads|VmRSS|VmSize):" "/proc/$pid/status"
        jcmd "$pid" GC.heap_info
        jcmd "$pid" VM.flags
    '
    docker inspect --format 'Memory={{.HostConfig.Memory}} PidsLimit={{.HostConfig.PidsLimit}} OOMKilled={{.State.OOMKilled}}' "$(dc ps -q transcriber)"

    Threads counts native threads. VmRSS is resident memory; heap used is not total process memory. Repeat measurements after meetings end. Sustained growth in idle thread counts is stronger evidence of a leak than one large busy snapshot. [S1][S5][S6]

  2. Docker: update older Whisper installations and repair backend failures. stable-11248 remains latest as checked October 6, 2026. Obtain matching release files following the upgrade guide, set JITSI_IMAGE_VERSION=stable-11248 in .env and run dc pull before recreation. Inspect with dc exec -T transcriber dpkg-query -W jigasi; released 1.1-415-g2750d54-1 contains PR #619. Investigate backend 403 responses using the Whisper setup. Larger limits do not repair authorization. [S1][S2][S3]

  3. Docker stable-11248: forward the heap setting and leave native headroom. In .env, set: [S3][S4]

    dotenv
    JIGASI_MAX_MEMORY=3072m

    Create this guide-specific overlay, transcriber-memory.yml: [S3][S10]

    YAML
    services:
      transcriber:
        environment:
          - JIGASI_MAX_MEMORY
        mem_limit: 4g

    This 4 GiB example exceeds the maintainer’s minimum; reserve host memory for other services and the speech backend. Update the helper, validate and recreate outside active sessions: [S1][S9][S10]

    Terminal
    dc() {
        docker compose -f docker-compose.yml -f transcriber.yml -f transcriber-memory.yml "$@"
    }
    dc config --quiet
    dc up -d --force-recreate transcriber

    Do not copy the issue’s experimental -Xss256k, pids_limit: 8192 or nproc changes as a leak fix. They were operator experiments, not a maintainer-approved recipe. Raising a task ceiling can merely postpone exhaustion. [S1][S6]

  4. Debian/Ubuntu Jigasi packages: measure the service. These steps cover 1.1-415-g2750d54-1. Use a matching JDK’s jcmd; the Docker image includes JDK 21, while your package runtime may differ. [S4][S5][S9]

    Terminal
    pid=$(systemctl show jigasi -p MainPID --value)
    test "$pid" -gt 0 || exit 1
    sudo grep -E '^(Threads|VmRSS|VmSize):' "/proc/$pid/status"
    sudo -u jigasi jcmd "$pid" GC.heap_info
    sudo -u jigasi jcmd "$pid" VM.flags
    systemctl show jigasi -p TasksCurrent -p TasksMax -p LimitNPROC -p MemoryCurrent -p MemoryMax

    Edit /etc/jitsi/jigasi/config, preserving other assignments. Set JIGASI_MAX_MEMORY=3072m, or a measured allocation your host supports, then run sudo systemctl restart jigasi. The unit reads this file and sets TasksMax=65000 and LimitNPROC=65000; inspect local overrides. For older packages with the Jitsi repository configured, update and verify: [S2][S4][S11][S13]

    Terminal
    sudo apt-get update
    sudo apt-get install --only-upgrade jigasi
    dpkg-query -W jigasi
  5. Both installations: size by measured concurrent load. No universal safe participants-per-Jigasi figure was established. Test simultaneous rooms, speakers, long sessions and backend failures. Add instances before resource saturation, with working brewery registration and backend capacity. Jicofo can select among registered transcribers using load and region preferences. More instances distribute new work; they do not cure leaking connections. [S1][S12]

Verify

For Docker, run dc exec -T transcriber printenv JIGASI_MAX_MEMORY. The example must print exactly 3072m. Inspect memory with docker inspect --format 'Memory={{.HostConfig.Memory}} OOMKilled={{.State.OOMKilled}}' "$(dc ps -q transcriber)". The healthy example prints: [S3][S10]

Text
Memory=4294967296 OOMKilled=false

For either installation, VM.flags should contain -XX:MaxHeapSize=3221225472 for this heap allocation. Then repeat start/speak/leave cycles and compare idle thread counts. Require working captions, no recurring backend failures and no continuing idle thread growth. These are acceptance checks, not load-test results from our server. [S2][S4][S5]

If it still fails

Capture jcmd "$pid" Thread.print as the JVM user before restarting. Use the same container or package context as above. Thread dumps help identify accumulating WebSocket pools; a small heap dump alone misses that evidence. [S1][S5]

Read Docker transcriber logs, or /var/log/jitsi/jigasi.log and sudo journalctl -u jigasi -n 200 --no-pager for packages. Check backend errors and effective task limits. On cgroup v2, pids.events records task-limit hits and memory.events records memory events; inspect the actual service/container cgroup rather than assuming a host path. [S4][S6][S11]

Use transcription troubleshooting if original captions never work, or the Vosk guide for backend setup. [S1]

FAQ

Will increasing Java heap fix EAGAIN?

Only if the measurements justify it. Thousands of retained threads with a small heap require connection cleanup and task/native-memory investigation. [S1][S6]

Why does my .env heap setting do nothing?

Stock stable-11248/transcriber.yml omits JIGASI_MAX_MEMORY. Explicitly forward it and recreate the container. [S3][S4]

Is this fixed upstream?

The Whisper failure-path fix is PR #619. The Vosk report remains unresolved as of October 6, 2026; PR #650 is still open and concerns a separate shutdown problem. [S1][S2][S8]

Sources

[S1] Issue #615, November 2025 to July 2026, community reports and maintainer comments; memory recommendation, backend diagnosis, maintainer comments.

[S2] Whisper PR #619, merged December 9, 2025, repository fix; released Whisper code, September 11, 2026, source code.

[S3] Transcriber Compose, source code; latest release, September 14, 2026, release note; package index, checked October 6, 2026, official repository; Docker handbook, official doc.

[S4] Jigasi launcher, packaged service, September 11, 2026, source code.

[S5] JDK 21 jcmd, matching diagnostic tools, checked October 6, 2026, official docs.

[S6] Thread creation limits, process status fields, official Linux manuals; cgroup v2 controllers, official kernel doc, checked October 6, 2026.

[S7] Diagnosing Java memory failures, checked October 6, 2026, official doc.

[S8] Whisper PR #650, September 25, 2026, proposed change, open as checked October 6, 2026; released Vosk client, September 11, 2026, source code.

[S9] Docker JDK installation, process tools, September 14, 2026, source code; pgrep, official Linux manual; rootless PR #2258, repository change.

[S10] Compose service limits, container inspection, Compose commands, checked October 6, 2026, official docs.

[S11] systemctl, journalctl, task and memory controls, official docs; Jigasi logs, source code, checked October 6, 2026.

[S12] Jicofo transcriber selection, September 2026, source code.

[S13] APT upgrade options, package query, official Debian manuals; Jitsi repository, official doc, checked October 6, 2026.

Open questions

No real-server thread-leak reproduction or capacity benchmark was run. The first Docker release shipping PR #619 was not established; its inclusion in the cited Jigasi release was verified. The Vosk error-path report is not fixed as of 2026-10-06. If you need measured capacity or multiple-instance setup, our transcription service can scope that work. [S1][S2]

Collect debug info

These commands gather what an engineer needs to diagnose a Jitsi server. Copy them, run them, and keep the output.

Terminal
# Run on the server, from your docker-jitsi-meet folder

# 1. Every service should be "running" (or "healthy")
docker compose ps

# 2. Which images and release tags are running
docker compose images

# 3. Recent logs from the core services
docker compose logs --tail=200 web prosody jicofo jvb

# 4. The settings most fixes depend on
grep -E '^(PUBLIC_URL|JVB_ADVERTISE_IPS|ENABLE_LETSENCRYPT|ENABLE_AUTH|AUTH_TYPE)=' .env

# 5. Is anything listening for media on UDP 10000?
sudo ss -ulnp | grep 10000

Installed with the Debian packages instead of Docker? Read the service logs with:

Terminal
sudo journalctl -u prosody -u jicofo -u jitsi-videobridge2 --since "1 hour ago"

Remove passwords, secrets and tokens before you share any output.

Send the output to an engineer

Stuck, or would rather not do this by hand?

Deploy it in one click

A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

Start free trial

Talk to a Jitsi engineer

Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

Get expert help

Related

Recently updated