Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

on-stop.sh: byte-level truncation splits multibyte UTF-8, Stop hook fails Claude Code JSON validation

Aperta Adatta ai principianti
#70 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
82/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Tranquilla
Stack tecnologico
bash
Ambito
cli, devtools

Direzione di ricerca

Inizia in scripts/on-stop.sh, alla troncatura di QUERY e RESPONSE, poi controlla legacy/on-stop.sh per lo stesso idioma. Esegui la riproduzione fornita della suddivisione ai confini e l'hook completo con le locale C e UTF-8. Il lavoro è completato quando il testo multibyte rimane UTF-8 valido e Claude Code accetta il JSON emesso.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

scripts/on-stop.sh (plugin v2.1.0) truncates the extracted query/response with bash substring expansion:

QUERY="${QUERY:0:197}..."
RESPONSE="${RESPONSE:0:197}..."

Bash slices by byte, not codepoint, when the hook runs without a UTF-8 locale (Claude Code hook subprocesses commonly inherit C/POSIX). When position 197 lands inside a multibyte character - em-dashes, arrows, box-drawing characters like ⎿ that Claude Code transcripts are full of - the truncated string ends with an invalid UTF-8 fragment. That fragment goes through jq --arg into the notification payload, and Claude Code rejects the hook's stdout:

Ran 6 stop hooks
  ⎿  Stop hook error: JSON validation failed

It is intermittent by nature: it only fires when byte 197 happens to split a character, so it looks flaky and is painful to attribute (Claude Code does not say which hook failed - see anthropics/claude-code#21992 for that class).

Reproduce

# 1. Craft a transcript whose last user message has a 3-byte char straddling byte 197
python3 - <<'EOF'
import json
q = 'a'*195 + '⎿ tail of the question'      # U+23BF = 3 bytes; bytes 196-198
lines = [
    {'type':'user','message':{'content': q}},
    {'type':'assistant','message':{'content':[{'type':'text','text': 'b'*195 + '— long response text'}]}},
]
open('/tmp/repro-transcript.jsonl','w').write('\n'.join(json.dumps(l) for l in lines))
EOF

# 2. Demonstrate the corruption the hook's truncation produces under a C locale
Q=$(jq -rs '[.[] | select(.type=="user")] | last | .message.content' /tmp/repro-transcript.jsonl)
LC_ALL=C bash -c 'Q="'"$Q"'"; printf "%s" "${Q:0:197}"' | python3 -c '
import sys
sys.stdin.buffer.read().decode("utf-8")'   # -> UnicodeDecodeError: invalid continuation byte

Running the full on-stop.sh against such a transcript with LC_ALL=C (and TERM_PROGRAM=WarpTerminal + a structured-notifications-capable Warp env) emits a payload containing the broken fragment, which fails Claude Code's stop-hook stdout schema validation.

Fix

Truncate codepoint-safely. jq is already a hard dependency of the script, so the smallest change is:

# Truncate for notification display (codepoint-safe; bash ${VAR:0:N} slices
# by byte under non-UTF-8 locales and can split a multibyte character).
if [ -n "$QUERY" ] && [ ${#QUERY} -gt 200 ]; then
    QUERY="$(printf '%s' "$QUERY" | jq -Rrs '.[0:197] + "..."')"
fi
if [ -n "$RESPONSE" ] && [ ${#RESPONSE} -gt 200 ]; then
    RESPONSE="$(printf '%s' "$RESPONSE" | jq -Rrs '.[0:197] + "..."')"
fi

Verified locally (patched plugin cache): valid JSON output across repeated runs under both UTF-8 and C locales, including the crafted boundary-splitting transcript above; the per-turn "JSON validation failed" error disappeared.

An equivalent guard likely belongs in legacy/on-stop.sh too if it shares the truncation idiom.

Environment

  • claude-code-warp plugin 2.1.0 (marketplace install)
  • Claude Code 2.1.197, macOS (darwin 25.5.0), bash 3.2 shebang path
  • Related-but-distinct: #63 (CRLF), #67 (notification spam) - same script, different bugs
Lingua principale
Shell
Stelle
231
Fork
56
Merge medio
4g 15h
PR unite (30g)
1

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di warpdotdev/claude-code-warp

Tutte le issue di warpdotdev/claude-code-warp

Issue simili

Altre issue su Shell/Bash

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.