Skip to content

[Bug]: iOS app lets a thread select Full access above a managed policy cap, then hangs retrying the refusal #32208

Closed

Description

@CWNathan

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/mobile

Steps to reproduce

  1. Run a T3 server with a managed policy that sets limits.maxRuntimeMode: "auto", with defaultRuntimeMode set to auto and locked.
  2. Pair the iOS app with that server and open a thread.
  3. Select Full access in the mode picker.
  4. Send a message in that thread.

This comes from one run. I haven't repeated it from a clean start, and my notes don't record which mode picker I used.

Expected behavior

Full access is greyed out with the policy's reason. If a change is refused anyway, the app says so, returns to the allowed mode, and the thread's messages still send.

Actual behavior

  • Full access could be selected, and the app showed no refusal.
  • The app kept sending the mode change. The server refused every attempt, about every 12–16 seconds while the app was open, for more than 35 minutes.
  • No message.dispatch reached the server for the thread's messages, so the thread looked hung on pending.
  • Setting the mode back and force-quitting did not clearly clear one thread, although the order of those steps wasn't recorded.

The cap itself held. Nothing ran in Full access, and the Claude processes ran with --permission-mode auto.

Impact

Minor bug or occasional failure

Version or commit

iOS app 2.2.0, server t3@0.1.7

Environment

Server on Linux, reached over Tailscale Serve, with the Claude provider.

Logs or stack traces

thread.runtime-mode.set refused: "<organization> limits threads to Auto."

Workaround

Archive the thread, which stops the retries, and start a new one. New threads worked normally.

Additional context

Two things I couldn't determine:

  • Why the option was selectable. At the v0.1.7 tag, ThreadSettingsSheet.tsx passes config?.managedPolicy to withManagedRuntimeModeLimits and disables the rows above the cap, so this should have been greyed out. The server sends managedPolicy in its config. The installed app build may differ from that tag, or another path may skip the limit.
  • What retries the command. I didn't trace it.

The closest existing reports, #29632 and #22957, describe different failures.

Drafted with Claude Code from my notes on the run, and reviewed by me.

Activity

  1. juliusmarminge commented on Nov 6, 2026

    @juliusmarminge
    Member

    Thanks for the detailed notes. I couldn't reproduce this on current main (b90e554). I ran a dev server with a policy that sets limits.maxRuntimeMode: "auto" and a locked defaultRuntimeMode: "auto". The client was the mobile dev build of the same commit, on an iOS simulator, with the Claude provider.

    • Your steps: In thread settings, Runtime shows Full access disabled with "Example Corp limits threads to Auto." Tapping it does nothing, and the thread stays on Auto. The next message was dispatched and ran normally. The server logged no thread.runtime-mode.set refusal.
    • Full access chosen before the cap applied: I picked Full access while the server ran without a policy, then restarted it with the policy. The thread shows "Example Corp limits threads to Auto. Switch this thread's mode to continue." with a Switch to Auto button. Sending anyway puts the message back in the composer with the same reason, and the app sends no mode change. I watched for 45 seconds with zero refusals. After Switch to Auto, the same message sent and ran.

    All three client-side pieces landed together with managed policy in d897d3f (#27197, 2026-11-01): the disabled rows, the notice, and the check that stops a queued message before it sends a refused mode change. The app's version string has read 2.2.0 since 2026-10-28, so a 2.2.0 build from before that commit has none of them. Such a build doesn't know about managedPolicy, so it offers Full access. It then retries the refused mode change on its 16-second backoff ceiling, which matches the 12–16 s you saw. Updating the app to a current build should fix it. Archiving and recreating the thread is no longer needed.

    Closing as fixed on main. If a current build still lets you pick Full access under the cap, please reopen and include the app's build number.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions