[BUG] Mobile permission approval lost on desktop: [bridge:repl] Failed to parse ingress message: undefined is not an object (evaluating 'H.rules.length') causes silent indefinite Bash hang

Resolved 💬 3 comments Opened Apr 26, 2026 by paulluuk Closed Apr 26, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When using Claude Code remote-control from a mobile client, Bash tool calls that require permission silently hang indefinitely. The mobile permission prompt does render, the user approves it, and the phone sends the approval response back to the desktop. But on the desktop side, the response handler in
bridge:repl throws while parsing the response, and the throw is logged only at DEBUG level. The in-flight tool call is never marked as approved, never dispatched, and never returns. The user sees nothing — no error, no prompt re-appearing, no progress indicator, no way to cancel from inside the
session. The session must be torn down externally (or the user waits for the remote bridge to time out, which in my case took ~12 minutes).

The Claude .exe process itself stays healthy and responsive throughout — ~0.47 sec CPU over a 5-second sample, no subprocess spawned. It is sitting idle in the permission queue waiting on an approval that already arrived but was discarded.

This affects any Bash command that triggers a fresh permission request. Once the failure occurs, no further Bash calls in that session can be approved either. Reads, Writes, and other tools that don't require Bash-style permissions continue to work normally during the hang, which is what initially made
this look intermittent / verb-specific.

What Should Happen?

hen the mobile client sends an approved control_response for a permission request, the desktop should:

  1. Parse the response.
  2. Mark the pending tool-use as approved.
  3. Dispatch the Bash tool call (tool_dispatch_start tool=Bash …).
  4. Return the tool result to the model.

If the response is malformed (or any handler in the parse path throws), the desktop should:

  1. Log the parse failure at [ERROR] (not [DEBUG]), so it surfaces in default operator-facing logs.
  2. Fail the in-flight tool-use with a synthetic error result rather than leave it queued forever, so the model regains control and can either retry or report back to the user.
  3. Honor the Bash tool's timeout parameter even at the pre-execution permission stage, so a stalled permission queue doesn't outlast an explicit deadline.

Error Messages/Logs

The decisive line, captured in ~/.claude/debug/<sessionid>.txt after running /debug on the next desktop session and grepping for Failed to parse:

  2026-04-26T18:11:37.881Z [DEBUG] [bridge:repl] Failed to parse ingress message: undefined is not an object (evaluating 'H.rules.length')

  Surrounding context showing the bug in the wider message flow:

  2026-04-26T18:11:34.515Z [DEBUG] Permission suggestions for Bash: [
    {
      "type": "addRules",
      "rules": [
        { "toolName": "Bash", "ruleContent": "git add *" },
        { "toolName": "Bash", "ruleContent": "echo \"ADD_EXIT=$?\"" }
      ],
      "behavior": "allow",
      "destination": "localSettings"
    }
  ]
  2026-04-26T18:11:34.516Z [DEBUG] [remote-bridge] Sent control_request request_id=59025a6d-2877-49e3-8483-f67cd2d2e70e
  2026-04-26T18:11:34.516Z [DEBUG] executePermissionRequestHooks called for tool: Bash
  2026-04-26T18:11:37.879Z [DEBUG] SSETransport: Event seq=212 event_id=cd372328-2d29-4ee6-ac68-aa7b3e112a7e event_type=control_response payload_type=control_response session=cse_01QgdZFNPjNkonHqw7eaK2Pf
  2026-04-26T18:11:37.880Z [DEBUG] [bridge:repl] Ingress message type=control_response
  2026-04-26T18:11:37.881Z [DEBUG] Persisting permission update: addRules to source 'localSettings'
  2026-04-26T18:11:37.881Z [DEBUG] [bridge:repl] Failed to parse ingress message: undefined is not an object (evaluating 'H.rules.length')

  After that line, no [Stall] tool_dispatch_start tool=Bash … ever appears for the pending toolUseId. The next 12 minutes of log are heartbeats and an unrelated hung MCP openDiff call:

  2026-04-26T18:11:50.125Z [DEBUG] MCP server "ide": Tool 'openDiff' still running (30s elapsed)
  …
  2026-04-26T18:20:50.146Z [DEBUG] MCP server "ide": Tool 'openDiff' still running (540s elapsed)

  Until session teardown:

  2026-04-26T18:23:46.323Z [DEBUG] [bridge:repl] Inbound control_request subtype=end_session
  2026-04-26T18:23:46.323Z [DEBUG] [bridge:repl] Sent control_response for end_session request_id=req_011CaSrFKBcEtW7J72u6E76c result=error
  2026-04-26T18:23:46.330Z [ERROR] SSETransport: Stream read error: The operation was aborted.
  2026-04-26T18:23:46.484Z [ERROR] CCRClient: Epoch mismatch (409), shutting down
  2026-04-26T18:23:46.485Z [WARN]  CCRClient: delivery batch failed: epoch superseded

  For comparison, in the same session a successful Bash dispatch produces this pair (from earlier in the log, when no parse error happened):

  2026-04-26T18:08:11.626Z [INFO]  [Stall] tool_dispatch_start tool=Bash toolUseId=… permissionDecisionMs=18935
  2026-04-26T18:08:11.729Z [INFO]  [Stall] tool_dispatch_end   tool=Bash toolUseId=… outcome=ok durationMs=104

  Independent confirmation that no subprocess spawned during the hang, captured via PowerShell at the time the session was wedged:

  ProcessId       : 72948
  Name            : claude.exe
  Responding      : True
  CPU             : 136.84  (delta over 5s sample: 0.469)
  WorkingSetMB    : 506.5
  Threads         : 52

  # Descendants of claude.exe (Win32_Process where ParentProcessId = 72948):
  (empty — no bash.exe, no git.exe, no anything)

  So the parent process is alive and idle, and no Bash/git child was ever spawned. The hang is unambiguously at the permission-gate handoff, not in the subprocess.

Steps to Reproduce

The bug is intermittent — same command shape sometimes succeeds, sometimes hits the parse error. But the conditions that significantly increase its frequency are clear: it requires a remote (mobile) client driving a desktop session, and a Bash call that triggers a fresh permission request (i.e. one
where the user gets a "Allow this command? / Always allow / Deny" prompt rather than one already covered by an existing allow rule).

Environment used to reproduce:

  • Desktop: Windows 11 Home 26200, claude 2.1.119 (C:\Users\menee\.local\bin\claude.exe).
  • Remote: Claude Code mobile client, connecting to the same conversation via the remote-bridge / SSE transport.
  • The repo doesn't matter; any project with a clean working tree works.

Steps:

  1. On the desktop, start a Claude Code session in any project directory: claude --debug (so ~/.claude/debug/<sessionid>.txt captures the events).
  2. From the mobile client, open the same session via remote control.
  3. From the mobile client, ask Claude to perform a Bash action that requires a fresh permission. The simplest reliable shape is a git-write-side command in a project where no git-allow rules exist yet:

Please create a small file .test_commit_marker.txt, stage it, and commit it.

  1. Claude will issue (a) a Write tool call to create the file, (b) a Bash call for git add, and (c) a Bash call for git commit -F …. The Write call uses Write-tool permissions and works fine; the Bash calls are where the bug fires. (git add is sufficient on its own — you don't need a full commit flow

to reproduce.)

  1. On the mobile client, when the permission prompt appears (e.g. "Allow git add *?"), tap to approve.
  2. Observe: nothing happens. The mobile and desktop both go silent. No tool result returns, no further model output, no progress.
  3. Wait at least 60 seconds to confirm the hang is real (not just slow).
  4. Run on the desktop, in a separate shell:

Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq <claude pid> } | Select Name, CommandLine

  1. Expected (bug present): empty result. No bash.exe or git.exe was ever spawned. The hang is at the permission gate, not in a wedged subprocess.
  2. Inspect ~/.claude/debug/<sessionid>.txt. Grep for Failed to parse ingress message. The matching line should be timestamped within ~5 ms of a [bridge:repl] Ingress message type=control_response line that came in immediately after the user's mobile approval.
  3. Confirm absence: grep the same log for [Stall] tool_dispatch_start tool=Bash matching the toolUseId of the pending request. There will be no such line — the permission gate never released, so dispatch never started.

Minimal repro file (the test marker the model writes in step 3):

.test_commit_marker.txt
-----------------------
This file exists only to give the model a tiny working-tree change to commit
during reproduction of the mobile-permission hang. Safe to delete.

Useful workaround for affected users while the bug is open:

Drive write-side Bash commands from the desktop client only. From a mobile session, ask the model to draft the commands as text and copy them into a real terminal — do not let the model invoke Bash through the harness while you're on mobile. Read-side tools (Read, Grep, Glob, Write, MCP, etc.) appear
unaffected because their permission flows don't go through the same bridge:repl parse path.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.119 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PyCharm terminal

Additional Information

I run Powershell in my PyCharm terminal.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗