Headless `-p --permission-mode dontAsk`: denied tool → run reports success (exit 0, is_error:false, subtype:"success")

Open 💬 1 comment Opened Jul 12, 2026 by NongKnot

Summary

In headless mode, when --permission-mode dontAsk denies a tool the task requires, the
run still reports success: process exit code 0, "is_error": false, "subtype":
"success"
, "stop_reason": "end_turn". The requested work is not done, yet nothing in the
exit code or the structured result marks the run as failed. The only signal is prose inside
result. This makes exit code / is_error unusable as a failure gate for unattended
automation.

Environment

  • Claude Code CLI, claude -p (print/headless), --output-format json
  • macOS (Darwin), observed 2026-07-11, re-confirmed 2026-07-12
  • gh/version irrelevant; reproducible with any tool that requires a permission prompt

Repro

D=$(mktemp -d); cd "$D"
claude -p --permission-mode dontAsk --output-format json --max-turns 3 \
  "Use the Write tool to create a file named probe.txt in the current directory containing the word hello. Do not ask, just do it."
echo "exit=$?"; ls probe.txt 2>&1

Observed

  • exit=0
  • probe.txt is not created (Write denied; the model also tried Bash, also denied)
  • JSON result: "is_error": false, "subtype": "success", "stop_reason": "end_turn"
  • result prose: "Both Write and Bash denied by don't-ask mode … Need permission to write probe.txt."

Expected

A run whose task could not be performed because every viable tool was denied should be
distinguishable from success without parsing free-text result. Options:

  • non-zero exit code, and/or
  • "is_error": true / a distinct subtype (e.g. "permission_denied" / "blocked"), and/or
  • a machine-readable field listing denied tool calls.

Impact

Unattended orchestrators (e.g. a bash loop that relaunches one headless session per unit of
work) cannot trust exit code or is_error to detect a permission-blocked run — they must
fall back to observing side effects (git/file state). Surfacing denial in the exit contract
would let such tools halt correctly instead of advancing past a no-op.

_Filed from Siri's all-agents toolkit (flow-v2 P-RT4). Runnable repro:
docs/upstream/dontask-exit0-repro.sh._

View original on GitHub ↗

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