[BUG] CLAUDE_CODE_ATTRIBUTION_HEADER=0 also blocks auto classifier model

Open 💬 4 comments Opened Jun 1, 2026 by chrisbennight

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When CLAUDE_CODE_ATTRIBUTION_HEADER=0 is set the auto classifier models fails with this message:

 ⎿  Error: claude-opus-4-8[1m] is temporarily unavailable, so auto mode cannot determine the safety of Write right now. Wait briefly and then try this action again. If it keeps failing, continue with other tasks that don't require this
     action and come back to it later. Note: reading files, searching code, and other read-only operations do not require the classifier and can still be used.

(for any model, not just opus)

when unsetting the variable it (auto classifier) works fine reliably

(variable set because of other documenting caching issues with it - i.e. https://github.com/anthropics/claude-code/issues/24168 )

What Should Happen?

Classifier model should not fail, or if this is an intentional anthropic position error message should be clearer.

Error Messages/Logs

Steps to Reproduce

  1. set CLAUDE_CODE_ATTRIBUTION_HEADER=0
  2. fire up claude code
  3. try to write a file to /tmp
  4. get error
  5. exit
  6. unset the var
  7. fire up claude code
  8. try to write a file to /tmp
  9. it works

repro script:

#!/usr/bin/env bash
# Repro: does CLAUDE_CODE_ATTRIBUTION_HEADER=0 break the auto-mode safety classifier?
#
# Method
# ------
# For each model, run `claude -p` in AUTO permission mode and force ONE benign Bash
# tool call that writes a sentinel file. The tool is deliberately NOT allowlisted, so
# the auto-mode safety classifier is the gate that must approve it. Therefore:
#   classifier OK     -> benign action approved -> sentinel file created
#   classifier broken -> "cannot determine the safety" -> blocked -> no sentinel
# Each model is run twice: control (header unset) vs test (header=0). A difference == repro.
#
# Oracle is the sentinel file (robust); the run log is kept for diagnosis and is also
# grepped for the classifier error string to distinguish a true block from any other
# failure.
#
# Models
# ------
# Default sweep: a stable Sonnet baseline, Opus 4.8, and Opus 4.8 with 1M context.
#   * claude-sonnet-4-6     -> clean baseline (widely available; control should pass)
#   * claude-opus-4-8       -> shows the header effect is not 1M-specific
#   * claude-opus-4-8[1m]   -> the variant from the original report
# NOTE: claude-opus-4-8[1m] is ALSO independently affected by transient Opus/1M-context
# capacity outages that emit the SAME error string. If its CONTROL run fails, that's the
# capacity bug, not the header — which is exactly why Sonnet is included as a clean control.
#
# Usage:
#   ./repro-attribution-classifier.sh
#   MODELS="claude-opus-4-8[1m]" ./repro-attribution-classifier.sh     # just the 1M variant
#   MODELS="claude-sonnet-4-6 claude-haiku-4-5" ./repro-...            # custom sweep
set -uo pipefail

CLAUDE="$(command -v claude)"
[ -z "$CLAUDE" ] && { echo "claude not on PATH"; exit 3; }

read -r -a MODELS <<< "${MODELS:-claude-sonnet-4-6 claude-opus-4-8 claude-opus-4-8[1m]}"

LOGDIR="$(mktemp -d /tmp/cc-classifier-logs.XXXXXX)"
TO="$(command -v timeout || command -v gtimeout || true)"
run_to(){ if [ -n "$TO" ]; then "$TO" 120 "$@"; else "$@"; fi; }
slug(){ printf '%s' "$1" | LC_ALL=C tr -c 'A-Za-z0-9' '_'; }

# run_case <model> <label> <env-modifiers...>   (env mod = `-u VAR` or `VAR=val`)
# sets globals: REPLY_CREATED (YES/NO), REPLY_BLOCKED (YES/no)
run_case(){
  local model="$1" label="$2"; shift 2
  local sentinel; sentinel="$(mktemp -u /tmp/cc-classifier-repro.XXXXXX)"
  local prompt="Use the Bash tool to run this exact command and nothing else, then stop: echo OK > ${sentinel}"
  local log="${LOGDIR}/$(slug "$model").${label}.log"
  rm -f "$sentinel"
  run_to env "$@" "$CLAUDE" -p "$prompt" \
      --permission-mode auto --model "$model" --output-format json \
      >"$log" 2>&1
  local ec=$?
  REPLY_CREATED="NO"; [ -f "$sentinel" ] && REPLY_CREATED="YES"
  REPLY_BLOCKED="no"; grep -qi "cannot determine the safety" "$log" && REPLY_BLOCKED="YES"
  printf '    %-8s exit=%-4s sentinel_created=%-4s classifier_blocked=%-4s  log=%s\n' \
         "$label" "$ec" "$REPLY_CREATED" "$REPLY_BLOCKED" "$log"
  rm -f "$sentinel"
}

echo "claude : $CLAUDE ($($CLAUDE --version 2>/dev/null))"
echo "models : ${MODELS[*]}"
echo "logs   : $LOGDIR"
echo

overall=0
for model in "${MODELS[@]}"; do
  echo "=== model: $model ==="
  echo "  [1/2] CONTROL  — CLAUDE_CODE_ATTRIBUTION_HEADER unset"
  run_case "$model" control -u CLAUDE_CODE_ATTRIBUTION_HEADER
  ctrl="$REPLY_CREATED"
  echo "  [2/2] TEST     — CLAUDE_CODE_ATTRIBUTION_HEADER=0"
  run_case "$model" test CLAUDE_CODE_ATTRIBUTION_HEADER=0
  test_created="$REPLY_CREATED"; test_blocked="$REPLY_BLOCKED"
  printf '  verdict: '
  if [ "$ctrl" = "YES" ] && [ "$test_created" = "NO" ]; then
    echo "REPRO CONFIRMED (control works; header=0 blocks; classifier_blocked=$test_blocked)"
  elif [ "$ctrl" = "NO" ]; then
    echo "INCONCLUSIVE — control did not execute (model unavailable / refused). See log."
    overall=1
  else
    echo "NOT REPRODUCED — both runs executed the action."
  fi
  echo
done
echo "all logs: $LOGDIR"
exit "$overall"

Output

bennight@Chriss-MacBook-Air projects % ./repro-attribution-classifier.sh
claude : /Users/bennight/.local/bin/claude (2.1.159 (Claude Code))
models : claude-sonnet-4-6 claude-opus-4-8 claude-opus-4-8[1m]
logs   : /tmp/cc-classifier-logs.c8u1e5

=== model: claude-sonnet-4-6 ===
  [1/2] CONTROL  — CLAUDE_CODE_ATTRIBUTION_HEADER unset
    control  exit=0    sentinel_created=YES  classifier_blocked=no    log=/tmp/cc-classifier-logs.c8u1e5/claude_sonnet_4_6.control.log
  [2/2] TEST     — CLAUDE_CODE_ATTRIBUTION_HEADER=0
    test     exit=0    sentinel_created=NO   classifier_blocked=YES   log=/tmp/cc-classifier-logs.c8u1e5/claude_sonnet_4_6.test.log
  verdict: REPRO CONFIRMED (control works; header=0 blocks; classifier_blocked=YES)

=== model: claude-opus-4-8 ===
  [1/2] CONTROL  — CLAUDE_CODE_ATTRIBUTION_HEADER unset
    control  exit=0    sentinel_created=YES  classifier_blocked=no    log=/tmp/cc-classifier-logs.c8u1e5/claude_opus_4_8.control.log
  [2/2] TEST     — CLAUDE_CODE_ATTRIBUTION_HEADER=0
    test     exit=0    sentinel_created=NO   classifier_blocked=YES   log=/tmp/cc-classifier-logs.c8u1e5/claude_opus_4_8.test.log
  verdict: REPRO CONFIRMED (control works; header=0 blocks; classifier_blocked=YES)

=== model: claude-opus-4-8[1m] ===
  [1/2] CONTROL  — CLAUDE_CODE_ATTRIBUTION_HEADER unset
    control  exit=0    sentinel_created=YES  classifier_blocked=no    log=/tmp/cc-classifier-logs.c8u1e5/claude_opus_4_8_1m_.control.log
  [2/2] TEST     — CLAUDE_CODE_ATTRIBUTION_HEADER=0
    test     exit=0    sentinel_created=NO   classifier_blocked=YES   log=/tmp/cc-classifier-logs.c8u1e5/claude_opus_4_8_1m_.test.log
  verdict: REPRO CONFIRMED (control works; header=0 blocks; classifier_blocked=YES)

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.159

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

_No response_

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗