[BUG] Literal "HERMES.md" in git commit messages triggers 400 "out of extra usage" on Max OAuth (content filter false-positive misclassified as quota error)

Resolved 💬 3 comments Opened Apr 25, 2026 by DUMPDUMPY Closed May 1, 2026

Summary

A literal HERMES.md string (uppercase + dot + md, case-sensitive) appearing anywhere in git log of the current working directory causes Claude Code on a Claude Max OAuth plan to return:

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"You're out of extra usage. Add more at claude.ai/settings/usage and keep going."}}

The error message is misleading — the Max plan has plenty of quota. This appears to be a server-side content filter false-positive (likely matching the canonical doc filename of an external AI project) that misroutes the request to the disabled "extra usage" lane.

Minimal Reproduction (10 lines, deterministic)

mkdir /tmp/repro-hermes && cd /tmp/repro-hermes
git init -q
echo a > a.txt && git add .
git commit -m "HERMES.md"          # exact case + .md is the trigger
claude
# > hi
# Result: API Error 400 "You're out of extra usage..."

Removing .git/ or rewording the commit message makes the error disappear instantly.

Trigger Specificity (case-sensitive byte match)

| Commit message | Result |
|---|---|
| HERMES.md | ❌ 400 |
| hermes.md | ✅ OK |
| Hermes.md | ✅ OK |
| HERMES (no .md) | ✅ OK |
| HERMES.txt | ✅ OK |
| HERMES md (no dot) | ✅ OK |
| 6 HARD GUARDS (other capitalized phrase from same commit) | ✅ OK |

The filter matches the literal byte sequence HERMES.md only — no case normalization.

What's not a trigger

| Scenario | Result |
|---|---|
| File named HERMES.md in working tree (no git) | ✅ OK |
| File content containing HERMES.md (no git) | ✅ OK |
| Auto-loaded CLAUDE.md containing HERMES.md text (no git) | ✅ OK |
| Env var HERMES_WEBHOOK_URL | ✅ OK |

The trigger is specifically in the bytes Claude Code derives from git log and sends as system context.

Real-world reproduction

A repo with 50 commits where 12 messages referenced HERMES.md returned 400 every time. Diagnosis path:

  • Shallow clone --depth 1 or --depth 2 (fewer than 3 commits visible) → ✅ works
  • --depth 3 (commit 607afc8 docs(...): HERMES.md 13-point review... becomes visible) → ❌ fails
  • git filter-repo --message-callback ...replace(b"HERMES.md", b"hermes-doc.md") → permanent fix

Why this matters

  1. The error message is wrong. Claims quota exhaustion when none exists, sending users to billing settings unnecessarily. Content-filter rejection misclassified as quota error.
  2. It silently blocks legitimate use. "Hermes" is a perfectly reasonable name (Greek mythology, classical themes, internal service names) and .md is standard for markdown docs.
  3. No actionable feedback. Users have no way to know the rejection is content-driven; the diagnostic path I followed (move CLAUDE.md → move .claude/ → remove project entry → bisect git history → bisect commit by commit → bisect message text → bisect words) took several hours.

Suggested fixes

  1. Don't classify content-filter rejections as billing errors. Return a distinct error type (e.g., content_filter_rejected) so clients can surface accurate messages.
  2. Reduce false-positive scope. Matching the literal byte sequence HERMES.md is too broad. Consider context-aware filtering, not bare substring match in free-form text.
  3. Document any system-context content that could be rejected so users can debug.

Environment

  • Claude Code: v2.1.119 (latest)
  • Plan: Claude Max 5x (OAuth, rateLimitTier=default_claude_max_5x)
  • Platform: Linux 6.8 (Ubuntu)
  • Auth: ~/.claude/.credentials.json, no ANTHROPIC_API_KEY set
  • Date observed: 2026-04-25
  • Related issues: #45020, #45033, #45028, #45095, #45390 (general "out of extra usage" reports — this is the first to identify a specific deterministic content-filter trigger)

---

Original real-world commit message that surfaced this bug

For full transparency / so engineers can analyze the byte sequences in case there is additional sub-pattern matching beyond the minimal HERMES.md trigger I isolated, here is the exact unmodified commit message in the repo that originally triggered the 400. Submitting verbatim because filter rules sometimes match on combinations / surrounding characters / unicode (em-dashes etc.) that minimal repros may not capture:

docs(session-118): HERMES.md 13-point review — profile model fix, schema, 6 HARD GUARDS, v0.11.0 notes

The 4 other commits in the same repo that also had HERMES.md in the message:

docs(session-118): update HERMES.md version to v0.11.0
docs: HERMES.md — Session 97c-fix5 Reviewer1 fallback + EP9 deprecation troubleshooting
- HERMES.md: Section 6 5-Layer Framework + ownOrderPlanId subsection + BANNED hindsight
HERMES.md updates:
- NEW HERMES.md (915 lines, 14 sections) — comprehensive Hermes Agent dev doc

Any of these in git log (depth ≥ that commit) → 400. Bisecting reduced the trigger down to HERMES.md alone, but the real-world messages contained additional content (em-dashes, parentheses, (session-NNN) prefix, all-caps phrases like BANNED, HARD GUARDS, version strings, etc.) that may share weight in whatever classifier is rejecting these.

View original on GitHub ↗

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