/auto-mode-setup always fails: "removeFromPermissionsAllow[0] is not a rule string the removal offer could have produced"

Status Open
Reported on v2.1.233
Maintainer reply None cached
Activity 1 comment · opened Aug 16, 2026

Summary

/auto-mode-setup fails deterministically with:

Auto-mode setup scan failed: removeFromPermissionsAllow[0] is not a rule
string the removal offer could have produced.

Reproduced 4 out of 4 runs, always at index [0]. The failure survives aggressive cleanup of every permission rule in every settings source, so it appears to be a bug in the setup command's draft/validate loop (the drafting model emits a removal string that doesn't exactly match any string in the gathered removal offer), not a user-config problem.

Environment

  • Claude Code 2.1.233 (npm install, @anthropic-ai/claude-code-linux-x64)
  • Linux x64
  • Auto mode already active before running the command: user settings have "permissions": { "defaultMode": "auto" } and an autoMode block with ["$defaults", "<one custom natural-language rule>"]
  • skipAutoPermissionPrompt: true

What was ruled out (each followed by a fresh failing run)

  1. Malformed rule strings in project .claude/settings.local.json — the allow list originally contained a rule with an unbalanced single quote and exact-match rules containing escaped double quotes and \\n sequences. All removed/normalized → still fails.
  2. Malformed rule strings in user ~/.claude/settings.local.json — ~24 more accumulated one-off rules containing double quotes, backslashes, $?/$! expansions, and unbalanced single quotes. All removed → still fails.
  3. Legacy vs modern rule syntax — the allow lists mixed the space form (Bash(git add *)) and the colon form (Bash(foo:*)). All remaining space-form rules were converted to :* form in both files, on the theory that the drafter normalizes syntax and breaks the exact-string match → still fails.
  4. Other rule sources — user settings.json has "allow": []; no project .claude/settings.json; no managed settings; no legacy projects.*.allowedTools entries in ~/.claude.json.

After step 3, every remaining rule in every source is a plain, well-formed string (no quotes, backslashes, or $), and the failure is unchanged.

Notes from the binary

Strings around the validator in the 2.1.233 linux-x64 binary show the offer is built from sections like #### permissions.allow entries auto mode ignores (classifier-bypassing, in your user settings) and #### Destructive permissions.allow entries (honored at runtime — auto-approved with no prompt, in your user settings), with validation messages removeFromPermissionsAllow must be an array of rule strings. / removeFromPermissionsAllow has N entries; the maximum is … / removeFromPermissionsAllow[N] is not a rule string the removal offer could have produced.

Two hypotheses that fit the always-[0], every-run failure:

  • the draft proposes removing a rule it saw in project/local settings while the offer set is built only from user settings (both section titles say "in your user settings"), or
  • the drafter reformats the rule string (syntax normalization, whitespace) so the exact-match check can never pass.

Either way, a validation failure here might be better surfaced as "draft rejected, retrying/skipping removals" rather than failing the whole setup scan, since the user has no way to act on the error.

Possibly relevant config shape

  • User-level allow list is large (~160 rules) accumulated across many projects.
  • Project-level allow list is small (~15 rules), and several of its entries (git, ssh) overlap with what auto mode's defaults/classifier would cover — i.e. plausible removal candidates.
  • autoMode.allow contains a custom natural-language rule that includes backtick-quoted command text.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗