[BUG] Remote Control: "Always allow" permission from Android app breaks tool calls

Status Open
Reported on v2.1.98
Maintainer reply None cached
Activity 13 comments · opened Apr 9, 2026

Summary

When approving a tool call from the Claude Code Android app via /remote-control with "always allow", the tool call fails with "internal error". Using "allow once" works normally. Approving from the local terminal works in both modes.

Environment

  • Claude Code 2.1.98
  • WSL2, Ubuntu 24.04.3 LTS, kernel 6.6.87.2-microsoft-standard-WSL2
  • Android app (latest)

Repro

  1. Start a Claude Code session in WSL terminal.
  2. Run /remote-control and connect from Android app.
  3. From the mobile app, prompt Claude to call a tool (e.g. WebFetch https://www.4foreverything.com/en).
  4. When the permission prompt appears, choose "always allow".
  5. Tool call returns [Tool result missing due to internal error] or session appears to hang.

Expected

Same behavior as "allow once" — the tool call executes and returns a result.

Actual

Tool call fails with internal error. Retrying with "allow once" works on the same URL/prompt.

Notes

  • Only happens when the prompt originates from the mobile remote-control channel. Local terminal prompts work with both permission modes.
  • May be related to a render-refresh issue: the terminal TUI sometimes doesn't redraw until a local keypress, which makes failures look like hangs.

View original on GitHub ↗

13 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/44435
  2. https://github.com/anthropics/claude-code/issues/28508
  3. https://github.com/anthropics/claude-code/issues/44847

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

Fefo83 · 4 months ago

This is not a duplicate of any of the listed issues:

  • #44435 is about a local PreToolUse hook missing a timeout field — unrelated to Remote Control.
  • #28508 is the closest in spirit (mobile-to-CLI sync failure), but covers AskUserQuestion selection drops, not tool permission handling. Different UX path, different failure mode.
  • #44847 is an architectural audit that mentions permission response drops as one of 15 issues, but is not a specific bug report with a reproducible case.

This issue is specifically and reproducibly about "Always allow" from the Android app failing with an internal error, while "Allow once" on the same prompt works fine. The narrow scope and clear repro steps make it worth keeping open separately.

aanvaribah · 4 months ago

Additional reproduction data — "Allow for session" via mobile app on .claude/ protected paths

I can reliably reproduce this with .claude/ (protected directory) edits approved via the Claude mobile app remote control.

Reproduction steps

  1. Run Claude Code on a Mac Mini via SSH (Termius or Claude app remote control)
  2. Have Edit(*) and Bash(*) in .claude/settings.local.json allow list
  3. Trigger an Edit to any file under .claude/ (e.g., .claude/skills/*/SKILL.md or .claude/hooks/*.py)
  4. The .claude/ hard-coded protection overrides the allow list and shows a permission prompt
  5. Approve with "Allow for session" via the Claude mobile app[Tool result missing due to internal error]
  6. Approve with "Allow once" via the Claude mobile app → works every time
  7. Approve with "Allow for session" via terminal (Termius SSH) → works every time

Systematic test results

| Test | Tool | Approval method | Interface | Result |
|------|------|----------------|-----------|--------|
| 1 | Edit | Allow once | Mobile app | Pass (even with 10min delay) |
| 2 | Edit (large, 15-line insertion) | Allow once | Mobile app | Pass |
| 3 | Edit | Allow for session | Mobile app | Inconsistent UI options |
| 4 | Edit | Allow once (after closing/reopening app) | Mobile app | Pass |
| 5 | Edit | Allow for session | Mobile app | Internal error |
| 5-retry | Edit (same file, same edit) | Allow once | Mobile app | Pass |
| 6 | Edit | Allow for session | Terminal (Termius) | Pass |
| 6-followup | Edit (no prompt — session allow persisted) | — | Terminal | Pass |

Additional observations

  • Hooks ruled out as a factor. Initially suspected a PreToolUse hook (check_write_path.py) that blocked writes outside the project directory might have contributed. Retired the hook and tested in a fresh session — bug persists identically. This is purely a mobile remote control issue, not hook-related.
  • The permission prompt UI in the mobile app sometimes shows "Allow once / Allow for session" and sometimes only "Allow once" — inconsistent across identical operations.
  • PermissionRequest hook logging confirms prompts fire for all tests, but session-level grants don't suppress subsequent prompts when approved via mobile app (they do when approved via terminal).

Environment

  • Claude Code 2.1.104
  • macOS (Darwin 25.4.0, arm64)
  • Claude mobile app (iOS) via remote control
  • Terminal: Termius SSH
koxon · 4 months ago

+1 — reproducing the same class of hang on Linux (Amazon Linux 2023, Claude Code latest, Opus 4.7 1M).

When a tool call requires permission approval (e.g. Edit on a file outside the project root — in my case a file in ~/ outside the cwd'd polybot repo), approving from the phone via /remote-control leaves the host CLI stuck:

  • On the phone, the approval appears to succeed (prompt dismisses).
  • On the host terminal, the permission prompt also appears to resolve as granted.
  • But the tool call itself never executes — Edit / Write / Bash hangs indefinitely. No error, no progress, no stream output.
  • The only unstick is a local keypress (Esc) on the host — same recovery path described in #51267.

This matches the "phone approves → host hangs" shape reported here, and overlaps with #51267 (silent host-side hang needing local keystroke). Happens on both "allow once" and "always allow" in my experience — so it may be broader than just the "always allow" path in the original report.

If it helps narrow the repro: the file I was editing was outside the project directory (home dir), which is what forced the permission prompt in the first place. Cross-dir edits may be a reliable trigger.

paulluuk · 4 months ago

+1 -- Adding a diagnosis from a Windows 11 desktop + Android Remote Control
session hitting this bug today. (Originally filed as #53612; closing
that as a duplicate of this issue.)

Captured via claude --debug after the hang. Sequence (timestamps in
ms — note 4 of these fall within a 2 ms window):

  • 18:11:34.515 — desktop sends control_request for Bash permission

with addRules suggestion: "git add *" and
"echo \"ADD_EXIT=$?\"", destination localSettings

  • 18:11:34.516 — [remote-bridge] Sent control_request request_id=<id>
  • 18:11:37.879 — mobile sends back control_response (user tapped

Always allow on the Android app)

  • 18:11:37.880 — [bridge:repl] Ingress message type=control_response
  • 18:11:37.881 — `Persisting permission update: addRules to source

'localSettings'`

  • 18:11:37.881 — `[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 session goes silent for ~12
minutes until the remote bridge tears it down with Stream read error:
The operation was aborted
+ CCRClient: Epoch mismatch (409).

Independent confirmation via PowerShell during the hang:

ProcessId :
Name : claude.exe
Responding : True
CPU delta (5s) : 0.469 sec # idle, not spinning
WorkingSetMB : 506.5

Win32_Process where ParentProcessId = → (empty)

i.e. claude.exe is alive and idle, with zero descendant processes —
no bash.exe or git.exe was ever spawned. The hang is at the
permission gate, not in a wedged subprocess.

The "Allow once" workaround already documented in this issue is
consistent with the diagnosis: that path doesn't go through
addRules-persistence and so doesn't hit the broken parser. Same
session, same command, "Allow once" succeeds; "Always allow" hangs.

### Two requests

  1. Severity escalation: this exact failure mode logs at [DEBUG].

It silently locks sessions for 10+ minutes. Worth promoting to
[ERROR] so it surfaces in default-level logs and any "report all
errors" tooling catches it.

  1. Defense-in-depth: when [bridge:repl] throws while parsing an

ingress message, the in-flight tool-use should be failed with a
synthetic error result rather than left queued indefinitely. That's
independently valuable from "fix the parser" — even a future parser
regression shouldn't be able to silently lock the session.

Environment: Windows 11 Home 26200, Claude Code 2.1.119,
C:\Users\menee\.local\bin\claude.exe. Android client connecting via
remote-bridge / SSE transport. No active git pre-commit hooks, no
GPG signing.

homelabchaos · 3 months ago

+1 — reproducing on Ubuntu 24.04.4 LTS, kernel 6.8.0-110, Claude Code v2.1.126 (latest as of 2026-05-03). Bug persists at this version.

Trigger path observation

Adding .git/hooks/* to the "protected paths" list that triggers this hang. Same failure mode aanvaribah described for .claude/ — the broad Edit allow at the user-settings level doesn't bypass it. Pattern across the 4 reports so far:

| Reporter | Protected path that triggered hang |
|---|---|
| Fefo83 (OP) | Bash WebFetch via /remote-control |
| aanvaribah | .claude/skills/*/SKILL.md |
| koxon | files in ~/ outside repo root |
| paulluuk | git add * permission rule |
| this comment | .git/hooks/pre-commit |

The common factor seems to be paths Claude Code treats as security-sensitive — git internals, Claude Code's own config, parent dirs of the working tree. Worth checking whether all of these go through a single "is this path in the protected list?" gate that produces the prompt that doesn't propagate back.

Reliable repro on this version

$ claude --remote-control     # in tmux, started via systemd Type=forking (claude-start.sh)
# In the conversation, ask the agent to Edit /home/picard/.git/hooks/pre-commit
# Edit prompt appears in Android Claude Code app
# Click "Allow for this session"
# Android app: prompt dismisses
# Terminal: tool call sits indefinitely; no progress indicator update; no token count change
# Recovery: Ctrl+C in terminal — model resumes with "user interrupted" tool result

100% reproducible across multiple sessions today. Switching the same approval to the terminal-side "Allow for session" works correctly (consistent with OP's observation that local terminal prompts work in both modes).

Workaround that worked

Approving from the local terminal (not mobile) succeeds even with "Allow for session". So the bridge is the unique failure path; once the response avoids it, the model wakes correctly.

Diagnostic data willing to share

If it'd help triangulate, I can capture (next time it hangs):

  • strace -p <claude-pid> -e trace=read,recv,recvfrom to see whether the host process is blocked on a pipe/socket read
  • pstree -p <claude-pid> to check for orphan tool subprocesses
  • Full claude --debug log around the prompt approval

Happy to provide if you want a specific platform-2 (native Linux + tmux + systemd) trace to compare against paulluuk's Windows trace.

Snailflyer · 3 months ago

The "Always allow" path combines two operations that need to stay atomic:

  1. persist a broader permission rule
  2. resolve the current in-flight permission prompt so the pending tool call can continue

Several repros here suggest the first operation can succeed while the second one fails or never completes. From the user perspective that is worse than a clean denial, because the app looks as if permission was granted but the host never dispatches the tool.

A safer contract would treat addRules persistence and prompt resolution as separate acknowledged states. If rule persistence succeeds but prompt resolution fails, the UI should surface approval_not_applied_to_pending_tool and give a retry/deny path instead of leaving the session hung.

AskYous · 3 months ago

Also hitting this on a different setup — adding details in case they help narrow it down.

Environment

  • Claude Code version: 2.1.150
  • Host: Ubuntu 22.04.4 LTS (Jammy) on Linode
  • Remote clients: macOS desktop GUI app (M4 Pro) and Android mobile app
  • Remote control enabled for all sessions

Differences from the original report

  • Reproduces from both the desktop GUI app and the Android mobile app, not just mobile — so this isn't phone-specific.
  • Intermittent for me, not 100%. Some approvals from the remote apps do go through; others hang exactly as described. Same command can succeed one approval and fail the next.
  • The remote app shows a persistent loading state after I tap Approve. Reconnecting via SSH shows the host session still waiting on the same prompt. Approving directly in the host terminal unblocks it.
  • After the hang, the approval prompt sometimes disappears entirely from the remote app UI — leaving the session looking idle/unresponsive with no indication that it's actually blocked on a permission prompt on the host.

Example commands where I've seen the hang

systemctl status claude-daemon --no-pager 2>/dev/null | head -20; echo "---LOGS---"; ls -la /var/log/claude-daemon/ 2>/dev/null | tail -5
sleep 15 && docker logs --since 15s 8cf58b7f9911 2>&1 | tail -10 && echo "---" && docker exec 8cf58b7f9911 sh -c 'printenv OPENROUTER_API_KEY | cut -c1-18'

Both are chained commands, but I've seen simpler commands hang too — I haven't found a pattern that predicts which approvals will fail.

Screenshots

Session appears unresponsive after the approval hang — no permission prompt visible in the UI, just my repeated follow-up messages to a silent session that's actually blocked on the host.

| Session 1 (linode 2) | Session 2 (localhost-rosy-mango) |
|---|---|
| <img width="320" alt="Image" src="https://github.com/user-attachments/assets/cc842f34-9cd6-44c9-b0ef-770053c787e2" /> | <img width="320" alt="Image" src="https://github.com/user-attachments/assets/d9382af2-0d77-46a0-9493-f748b930c9f3" /> |

omatheusmesmo · 3 months ago

+1

raulillo82 · 3 months ago

+1

Claude Code running in cli in opensuse tumbleweed, usually within "screen". Using remote control in Android app.

GeneralAnalytics · 3 months ago

Still reproducible on 2.1.158 (native Linux, Debian 13 / trixie; CLI run under systemd in a detached tmux). Phone: Android 16.

Same split as the original report: from the mobile app, "Allow once" works every time, "Always allow / don't ask again" hangs the host session indefinitely. The host-side prompt logic is fine — pressing the corresponding option key in the local TTY clears it instantly and the tool runs, so the break is specifically in delivery/handling of the persisting approval variant over the remote-control channel.

One extra data point: after the local keypress confirms the "always allow" option, the rule does not end up written to settings.local.json, so the remember-this path looks broken end-to-end, not just a missing UI ack.

it-rec · 2 months ago

This blocks me since month.

On mobile I can allow something but the same time one the host it doesn't do anything.

The approval seems to never properly reach the host in a way that it works like a local approval.

tigerhawkvok · 2 months ago

Still repros on Claude 2.1.198 on Ubuntu with Android app 1.260625.20