openclaw - ✅(Solved) Fix Inbound image processing hangs silently in WSL2 due to GNOME Keyring blocking [2 pull requests, 4 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#59104Fetched 2026-04-08 02:28:32
View on GitHub
Comments
4
Participants
2
Timeline
11
Reactions
0
Timeline (top)
commented ×4mentioned ×3subscribed ×3cross-referenced ×1

Sending any image to OpenClaw causes the gateway to hang silently. The image downloads successfully, dispatch begins, but then produces zero output — no API request logged, no error, no session JSONL write. The gateway process also becomes unresponsive to SIGTERM, requiring systemd SIGKILL after timeout. Queued messages are lost on restart.

This issue was introduced in v2026.3.31 (specifically by PR #55513). It does not occur on v2026.3.28.

Error Message

Sending any image to OpenClaw causes the gateway to hang silently. The image downloads successfully, dispatch begins, but then produces zero output — no API request logged, no error, no session JSONL write. The gateway process also becomes unresponsive to SIGTERM, requiring systemd SIGKILL after timeout. Queued messages are lost on restart.

  • No error is thrown
  1. A clear error should be logged instead of silent hang

Root Cause

The hang is caused by GNOME Keyring blocking synchronously in WSL2.

When OpenClaw's new attachment processing path (introduced by PR #55513) processes inbound images, it appears to trigger Chromium (via puppeteer/playwright, cached at ~/.cache/puppeteer/chrome or ~/.cache/ms-playwright). Chromium attempts to access GNOME Keyring via D-Bus/libsecret for credential storage.

In WSL2, this keyring access blocks synchronously with no timeout:

  • No error is thrown
  • No logs are written after the block occurs
  • The process thread is stuck indefinitely
  • SIGTERM cannot interrupt the blocked thread

The key breakthrough was observing a Windows GUI popup titled "Choose password for new keyring" (from WSLg's D-Bus bridge). After dismissing this popup, subsequent image dispatches completed successfully without hanging.

Fix Action

Workaround

Add these environment variables to the OpenClaw gateway service:

Environment="GNOME_KEYRING_CONTROL=" "KEYRING_DISABLED=1"

PR fix notes

PR #60278: fix(agents): bypass loadWebMedia for media-uri refs to prevent WSL2 keyring deadlock (#59104)

Description (problem / solution / changelog)

Summary

  • Problem: loadImageFromRef passed a local filesystem path (returned by resolveMediaBufferPath) to loadWebMedia for media-uri refs.
  • Why it matters: On WSL2 / Ubuntu 24.04, loadWebMedia launches Chromium, which attempts to access GNOME Keyring via libsecret. This causes a synchronous block, making the Gateway hang silently with no logs, no errors, and no response to SIGTERM.
  • What changed: Bypassed the Chromium browser stack completely for media-uri refs. Replaced loadWebMedia(physicalPath) with a direct fs.readFile(physicalPath) call.
  • What did NOT change (scope boundary): The handling of standard remote web URLs and inline image references remains untouched.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #59104
  • Related #
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: Attempting to use a headless browser stack (Chromium) to load an already-validated and persisted local media file.
  • Missing detection / guardrail: Missing differentiation in the loading strategy between remote URLs (which need browser rendering/fetching) and local Gateway-managed files.
  • Prior context (git blame, prior PR, issue, or refactor if known): Unknown
  • Why this regressed now: Unknown
  • If unknown, what was ruled out: N/A

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/pi-embedded-runner/run/images.test.ts (or equivalent)
  • Scenario the test should lock in: Assert that providing a media-uri ref calls fs.readFile and strictly does NOT invoke loadWebMedia.
  • Why this is the smallest reliable guardrail: It prevents the heavy browser stack from being invoked for local files, which is the direct trigger for the OS-level keyring deadlock.
  • Existing test that already covers this (if any): None
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

None. The Gateway will now successfully process images on WSL2 instead of silently crashing.

Diagram (if applicable)

Before:
[media-uri ref] -> [loadWebMedia(Chromium)] -> [libsecret / GNOME Keyring] -> [Deadlock / Gateway Hangs]

After:
[media-uri ref] -> [fs.readFile] -> [Base64 Image Data Returned]

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: WSL2 / Ubuntu 24.04
  • Runtime/container: Node.js (Local)
  • Model/provider: Any vision-capable model
  • Integration/channel (if any): WebUI / Chat
  • Relevant config (redacted): N/A

Steps

  1. Run Gateway on WSL2 (Ubuntu 24.04).
  2. Send a large image attachment (e.g., >2MB) in the chat to trigger the claim-check offload path (media-uri).
  3. Observe Gateway behavior.

Expected

  • The image is loaded, processed, and the model responds normally.

Actual

  • Before this PR: Gateway hangs silently, consumes CPU/RAM without returning, ignores SIGTERM.
  • After this PR: Gateway processes the image instantly via local filesystem read.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: Reproduced the deadlock on WSL2 with large images. Applied the fix and verified the image loads successfully via fs.readFile without launching Chromium.
  • Edge cases checked: Verified small images (inline paths) are unaffected. Verified MIME type is correctly inferred from the persisted file extension.
  • What you did not verify: Did not test on macOS/native Windows, as the keyring deadlock is specific to Linux/WSL2 desktop environments.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: MIME type inference now relies on the local file extension rather than browser headers.
    • Mitigation: The Gateway's saveMediaBuffer already strictly validates and assigns the correct extension during the initial offload/persist phase, making the file extension a reliable source of truth.

Changed files

  • src/agents/pi-embedded-runner/run/images.test.ts (modified, +26/-0)
  • src/agents/pi-embedded-runner/run/images.ts (modified, +55/-15)

PR #62873: fix(sandbox): prevent false-positive CDP readiness and add fail-fast

Description (problem / solution / changelog)

Summary

Problem: In headless Docker/WSL2 environments, the sandbox Chromium silently hangs indefinitely while waiting for a non-existent system keyring (libsecret). The socat proxy was masking this failure by immediately keeping the TCP port open, causing the Node.js host to receive a "false-positive" readiness signal and wait endlessly.

Why it matters: This causes a permanent, silent deadlock in the image processing pipeline, wasting resources and defeating the system's self-healing (docker rm -f) capabilities.

What changed (Hotfix):

  1. Keyring Bypass: Bypassed the keyring deadlock via --password-store=basic, --use-mock-keychain, and DBUS_SESSION_BUS_ADDRESS=/dev/null.
  2. Fail-Fast Watchdog: Added a strict curl health check loop. If CDP does not return a valid response within 30 seconds, the entrypoint triggers kill -9 and exit 1.
  3. Socat Deferral (Core Fix): Moved the socat startup to after the CDP health check passes. This eliminates the false-positive readiness signal.
  4. Lifecycle Binding: Replaced wait -n with wait "$CHROME_PID" to strictly bind the container's lifecycle to the Chromium main process instead of arbitrary background jobs.

What did NOT change: The socat proxy and CDP port offset logic remain in place for now to ensure architectural compatibility. (The complete removal of socat and transition to direct CDP routing will be addressed in a follow-up architectural PR). The downstream image optimization logic and media-uri handling remain untouched.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #59104
  • Related #60278
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: Chromium in a headless Debian/Docker environment blocks indefinitely on the D-Bus/Keyring daemon. The socat proxy returned a false-positive connection state to the host.
  • Missing detection / guardrail: The sandbox-browser-entrypoint.sh curl loop failed silently instead of exiting. The Node.js waitForSandboxCdp lacked a mechanism to garbage-collect hung containers on timeout.
  • Contributing context: WSL2 + Docker Desktop lacks native desktop GUI daemons (like gnome-keyring), easily triggering Chromium's blocking behavior.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/sandbox/browser.ts
  • Scenario the test should lock in: Ensure docker rm -f is correctly executed when waitForSandboxCdp breaches its timeout threshold.
  • Why this is the smallest reliable guardrail: Validates the host-boundary auto-recovery mechanism without requiring a full failing browser setup.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: This PR focuses on architectural hardening. E2E container tests are needed to simulate keyring deadlocks natively.

User-visible / Behavior Changes

None. System reliability and operator observability are significantly improved.

Diagram (if applicable)

Before (Silent Deadlock & False Positive):[Chromium hangs][socat starts & holds port][Node.js waits infinitely]

After (Fail-Fast & Auto-Recovery):[Chromium starts][Health check loop 30s]     ┣━ (Fail)[exit 1][Container dies][docker rm -f]     ┗━ (Pass)[Start socat][Node.js connects safely]

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? Yes
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation:
  • Mitigation: Safe because container isolation remains intact; host access is strictly managed via Docker's port mapping (-p 127.0.0.1::CDP_PORT).

Repro + Verification

Environment

  • OS: Windows (WSL2)
  • Runtime/container: Docker Desktop / Debian slim
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): Standard local sandbox configuration.

Steps

  1. Send an image payload to trigger the browser sandbox offload pipeline in a WSL2 Docker environment.
  2. Observe the Chromium container startup phase.

Expected

  • Chromium successfully exposes the CDP port and processes the image, or the container immediately dies if CDP fails, triggering a clean host-side timeout and container recreation.

Actual

  • (Before this PR) The container silently hung, locking up the Node.js thread waiting for the sandbox indefinitely.

Evidence

  • Trace/log snippets

Human Verification (required)

  • Verified scenarios: 1. Manually crashing the CDP endpoint to verify the entrypoint script executes exit 1. 2. Forcing a timeout in waitForSandboxCdp to verify docker rm -f cleans up the dead container.
  • Edge cases checked: Ensured noVnc and --no-sandbox configurations are still parsed and applied correctly without the socat layer.
  • What you did not verify: Full regression on macOS/Linux native environments (relies on CI).

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Hardcoding 0.0.0.0 in Chromium args could theoretically expose CDP if the Docker container is run with --network host.
    • Mitigation: The Sandbox runner inherently isolates networks and binds mapped ports exclusively to 127.0.0.1 on the host side.

Changed files

  • scripts/sandbox-browser-entrypoint.sh (modified, +126/-46)
  • src/agents/sandbox/browser.create.test.ts (modified, +36/-0)
  • src/agents/sandbox/browser.ts (modified, +7/-7)
  • src/agents/sandbox/config-hash.test.ts (modified, +4/-0)
  • src/agents/sandbox/config-hash.ts (modified, +7/-1)

Code Example

[INFO] media resolved: 1 attachment(s)
[INFO] dispatching to agent
(zero output for 3.5+ minutes)
SIGTERM → no response → systemd SIGKILL after 30s

---

Environment="GNOME_KEYRING_CONTROL=" "KEYRING_DISABLED=1"
RAW_BUFFERClick to expand / collapse

Title: Inbound image processing hangs silently in WSL2 due to GNOME Keyring blocking

Body

Environment

  • OS: Ubuntu 24.04 on WSL2 (Windows 11, WSLg enabled)
  • OpenClaw: v2026.3.31 (213a704)
  • Node.js: v24.14.0
  • Service manager: systemd user service
  • Channel: Feishu (websocket), but likely affects all channels

Description

Sending any image to OpenClaw causes the gateway to hang silently. The image downloads successfully, dispatch begins, but then produces zero output — no API request logged, no error, no session JSONL write. The gateway process also becomes unresponsive to SIGTERM, requiring systemd SIGKILL after timeout. Queued messages are lost on restart.

This issue was introduced in v2026.3.31 (specifically by PR #55513). It does not occur on v2026.3.28.

Root Cause

The hang is caused by GNOME Keyring blocking synchronously in WSL2.

When OpenClaw's new attachment processing path (introduced by PR #55513) processes inbound images, it appears to trigger Chromium (via puppeteer/playwright, cached at ~/.cache/puppeteer/chrome or ~/.cache/ms-playwright). Chromium attempts to access GNOME Keyring via D-Bus/libsecret for credential storage.

In WSL2, this keyring access blocks synchronously with no timeout:

  • No error is thrown
  • No logs are written after the block occurs
  • The process thread is stuck indefinitely
  • SIGTERM cannot interrupt the blocked thread

The key breakthrough was observing a Windows GUI popup titled "Choose password for new keyring" (from WSLg's D-Bus bridge). After dismissing this popup, subsequent image dispatches completed successfully without hanging.

Evidence

Reproducible steps:

  1. Run OpenClaw v2026.3.31 in WSL2 as a systemd user service
  2. Send any image (<2MB, tested with 244KB and 385KB JPEGs) via any channel
  3. Gateway hangs silently

Debug log sequence (reproduced 3 times with identical signature):

[INFO] media resolved: 1 attachment(s)
[INFO] dispatching to agent
(zero output for 3.5+ minutes)
SIGTERM → no response → systemd SIGKILL after 30s

What does NOT help:

  • Changing the model (reproduces on text-only glm-5-turbo AND vision-capable glm-4.6v)
  • Configuring imageModel (only affects the agent-exposed image tool, not dispatch path)
  • Adding vision models to fallbacks (hang occurs before any model API call)

What DOES fix it temporarily:

  • Dismissing the GNOME Keyring popup allows subsequent images to process
  • Adding GNOME_KEYRING_CONTROL= and KEYRING_DISABLED=1 to the service environment prevents the popup and allows normal image processing

Expected Behavior

Either:

  1. The attachment processing should not trigger Chromium/keyring access, OR
  2. If keyring access is needed, it should have a timeout and fall back gracefully instead of blocking indefinitely, OR
  3. A clear error should be logged instead of silent hang

Workaround

Add these environment variables to the OpenClaw gateway service:

Environment="GNOME_KEYRING_CONTROL=" "KEYRING_DISABLED=1"

Additional Notes

  • OpenClaw's node_modules has no direct keyring/keytar/libsecret dependencies — the trigger comes purely from bundled Chromium
  • This may affect other non-WSL Linux environments where GNOME Keyring is installed but not properly initialized (e.g., headless servers)
  • PR #55513 introduced media://inbound/<id> opaque URI offloading for attachments 2-5MB and inline base64 for <2MB. Both paths appear to trigger the Chromium dependency

Related

  • The SIGTERM unresponsiveness during this hang is a secondary issue — a stuck task should not block graceful shutdown

extent analysis

TL;DR

To fix the silent hang in OpenClaw when processing inbound images in WSL2, add the environment variables GNOME_KEYRING_CONTROL= and KEYRING_DISABLED=1 to the service configuration.

Guidance

  • Identify the version of OpenClaw being used and confirm it is v2026.3.31, as this issue was introduced in this version.
  • Verify that the hang occurs when sending images via any channel and that the process becomes unresponsive to SIGTERM.
  • Apply the workaround by adding the environment variables GNOME_KEYRING_CONTROL= and KEYRING_DISABLED=1 to the OpenClaw gateway service configuration to prevent the GNOME Keyring popup and allow normal image processing.
  • Consider testing with different image sizes and types to ensure the workaround resolves the issue in all scenarios.
  • Be aware that this issue may also affect other non-WSL Linux environments where GNOME Keyring is installed but not properly initialized.

Example

To apply the workaround, add the following lines to the OpenClaw service configuration file:

Environment="GNOME_KEYRING_CONTROL=" "KEYRING_DISABLED=1"

This will prevent the GNOME Keyring popup and allow image processing to complete without hanging.

Notes

The root cause of the issue is the synchronous blocking of GNOME Keyring access in WSL2, which is triggered by the new attachment processing path introduced in PR #55513. The workaround prevents this blocking by disabling the keyring, but a more permanent fix may be needed to handle keyring access properly.

Recommendation

Apply the workaround by adding the environment variables GNOME_KEYRING_CONTROL= and KEYRING_DISABLED=1 to the OpenClaw gateway service configuration, as this is a straightforward and effective solution to prevent the silent hang when processing inbound images in WSL2.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING