[BUG] Remote Control: "Always allow" permission from Android app breaks tool calls
Status Open
Reported on v2.1.98
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
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
- Start a Claude Code session in WSL terminal.
- Run
/remote-controland connect from Android app. - From the mobile app, prompt Claude to call a tool (e.g.
WebFetch https://www.4foreverything.com/en). - When the permission prompt appears, choose "always allow".
- 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.
13 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This is not a duplicate of any of the listed issues:
PreToolUsehook missing a timeout field — unrelated to Remote Control.AskUserQuestionselection drops, not tool permission handling. Different UX path, different failure mode.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.
Additional reproduction data — "Allow for session" via mobile app on
.claude/protected pathsI can reliably reproduce this with
.claude/(protected directory) edits approved via the Claude mobile app remote control.Reproduction steps
Edit(*)andBash(*)in.claude/settings.local.jsonallow list.claude/(e.g.,.claude/skills/*/SKILL.mdor.claude/hooks/*.py).claude/hard-coded protection overrides the allow list and shows a permission prompt[Tool result missing due to internal error]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
PreToolUsehook (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.PermissionRequesthook 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
+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.
Editon a file outside the project root — in my case a file in~/outside the cwd'd polybot repo), approving from the phone via/remote-controlleaves the host CLI stuck:Edit/Write/Bashhangs indefinitely. No error, no progress, no stream output.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.
+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 --debugafter the hang. Sequence (timestamps inms — note 4 of these fall within a 2 ms window):
with addRules suggestion:
"git add *"and"echo \"ADD_EXIT=$?\"", destinationlocalSettings[remote-bridge] Sent control_request request_id=<id>Always allow on the Android app)
[bridge:repl] Ingress message type=control_response'localSettings'`
undefined is not an object (evaluating 'H.rules.length')`
After that line, no
[Stall] tool_dispatch_start tool=Basheverappears 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.exeis alive and idle, with zero descendant processes —no
bash.exeorgit.exewas ever spawned. The hang is at thepermission 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. Samesession, same command, "Allow once" succeeds; "Always allow" hangs.
### Two requests
[DEBUG].It silently locks sessions for 10+ minutes. Worth promoting to
[ERROR]so it surfaces in default-level logs and any "report allerrors" tooling catches it.
[bridge:repl]throws while parsing aningress 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 viaremote-bridge / SSE transport. No active git pre-commit hooks, no
GPG signing.
+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 broadEditallow 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
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,recvfromto see whether the host process is blocked on a pipe/socket readpstree -p <claude-pid>to check for orphan tool subprocessesclaude --debuglog around the prompt approvalHappy to provide if you want a specific platform-2 (native Linux + tmux + systemd) trace to compare against paulluuk's Windows trace.
The "Always allow" path combines two operations that need to stay atomic:
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
addRulespersistence and prompt resolution as separate acknowledged states. If rule persistence succeeds but prompt resolution fails, the UI should surfaceapproval_not_applied_to_pending_tooland give a retry/deny path instead of leaving the session hung.Also hitting this on a different setup — adding details in case they help narrow it down.
Environment
Differences from the original report
Example commands where I've seen the hang
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" /> |
+1
+1
Claude Code running in cli in opensuse tumbleweed, usually within "screen". Using remote control in Android app.
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.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.
Still repros on Claude 2.1.198 on Ubuntu with Android app 1.260625.20