iOS app: every Remote Control send fails "Failed to send message - The request was invalid", while the web client works on the same session
Environment
- Claude Code 2.1.215 on Windows 11 (host/tower)
- iOS Claude app: latest App Store version as of 19 Jul 2026, iPhone
- Two accounts tried, both with Max subscriptions
- Remote Control hosting tried in both shapes:
claude remote-control --permission-mode auto --spawn same-dir(server mode; sessions created from the phone's "New session" flow)claude --remote-control=<name>(foreground TUI attach-in-place)
Summary
Every message sent from the iOS app to any Remote Control session fails instantly with
"Failed to send message — The request was invalid." The same sessions accept sends from the
claude.ai/code web client immediately (reply streams back and mirrors into the tower TUI).
Instrumented --debug-file logs on the host show the phone-originated turns never reach the
environment bridge — the rejection happens in the app/cloud before the tower is involved.
What works from the iOS app
- Device discovery (tower shows as one device, Active)
- Directory/environment browse (multi-server picker keyed by full path — correct)
- Session creation against a spawn-mode server (bridge log shows the session created + adopted; child
process spawns healthy: SessionStart hooks run, MCP servers connect, SSE event stream up, heartbeats
every 20 s)
Only the send fails.
Eliminated (all tested live, identical failure)
| Variable | Tested | Result |
|----------|--------|--------|
| Account | 2 different accounts (both Max) | fails on both |
| Model | Opus 4.8 and Sonnet (switched in-session) | fails on both |
| Session shape | spawn-mode server session AND --remote-control TUI-attach session | fails on both |
| Usage window | retried on an account with a fresh 5h window | fails |
| App version | latest App Store build | fails |
| Composer permission chip | flipped "Manual" → auto/default before sending | fails |
| Host health | instrumented bridge + child debug logs | clean; turn never arrives |
| Same session from web | claude.ai/code, same session URL | works |
The decisive split (same session, same account, same host)
- iOS app → session
session_01JiNTWLbdYZEwoozGoo6cQs(TUI-attach, auto mode): "The request was invalid" - Web client → same session: send succeeds, response renders on web and mirrors in the host TUI
- Web client → the spawn-mode environment (
env_01DFUgEG9mzPivoFS4ifj1VH) → new session → send: works
Host-side bridge debug log contrast:
# during all iOS-app attempts (12:47Z–13:02Z window, 19 Jul 2026):
GET .../work/poll -> 200 (no work, 500 consecutive empty polls)
GET .../work/poll -> 200 (no work, 600 consecutive empty polls)
# child for the app-created session stays healthy throughout:
SSETransport: SSE URL = https://api.anthropic.com/v1/code/sessions/cse_015nAERELeM7iXaapgCuw96x/worker/events/stream
CCRClient: Heartbeat sent (every 20 s, continuously)
# the moment a WEB send was made instead (14:01:50Z):
GET .../work/poll -> 200 workId=cse_0189z8TCSJC1mdbbGGaztexS type=session sessionId=[REDACTED]
Repro steps
- On a Windows host:
claude remote-control --permission-mode auto --spawn same-dirin a trusted dir
(or claude --remote-control=name in a TUI).
- iOS app → Code tab → pick the device/directory → new session (or open the TUI session).
- Send any message (e.g. "reply OK").
- Observe instant "Failed to send message — The request was invalid." Host debug logs show no
incoming work item.
- Open the same session at claude.ai/code in a desktop browser → send the same text → works.
Additional notes
- The error string appears nowhere in the RC troubleshooting docs or error reference.
hasAvailableSubscriptionin.claude.jsonreadsFalseon both (subscribed, working) accounts on
this build — unrelated red herring, noted in case it confuses triage.
- Full
--debug-filebridge + per-session child logs retained and available on request.
Workaround
claude.ai/code in a browser (desktop or mobile Safari) drives the same RC sessions correctly.