[BUG] False positive: [bio] safeguard fires on base64 file-comparison work, then hard-blocks the conversation (request IDs included)
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?
Summary
During ordinary file-editing work in Claude Code, a [bio] safeguard classifier flagged the
turn and forced a model switch from Fable 5 to Opus 5. Nothing in the session was
biology-related. The work was: insert a paragraph into a Markdown file, then verify the edit by
comparing file bytes.
The notice, verbatim
Fable 5's safeguards flagged this message
Our intentionally broad safeguards allow us to deliver more capabilities faster, but can
sometimes flag legitimate coding, cybersecurity, and biology tasks. Switched to Opus 5.
Details: [bio]
When
2026-08-20, between 22:16Z and 22:25Z. Claude Code desktop app on Windows 11.
A screenshot of the notice is available on request.
A third occurrence, with a request id — please start here
Later the same evening, in the same conversation, a message was hard-blocked rather than
redirected. Details: [bio], and:
Request ID: req_011CeEsXKMupfJQ766ULp6Zj
Request was blocked
Opus 5's safeguards flagged this message (https://www.anthropic.com/legal/aup). ... Claude Code
can't respond to this message with Opus 5.
Try rephrasing the request in a new session or change your model.
This one is the most diagnostic of the three, for three reasons:
- It is a block, not a fallback — the session was already on Opus 5, so there was no further
fallback available, and the user simply lost the turn.
- The blocked message contained **no base64, no file content, and no medical or biological
terms**. It was a plain-English question asking whether the base64 encoding step could be
moved out of the model's context and into a deterministic Python script run under a service
account.
- It therefore suggests the flag is driven by accumulated conversation context rather than by
the current message — consistent with the documented behavior that the checks review
everything the model reads and that a trigger persists within a conversation.
A user asking how to avoid tripping a false positive was blocked for asking. That is worth a look
on its own.
A fourth occurrence — cleanest example of the four
Shortly afterwards, in the same conversation, a second hard block:Details: [bio], Request ID req_011CeEveDErfJs3U5mapbF3R, same wording.
The blocked turn consisted of one grep over local Markdown notes, searching for the words
"collision" and "values.append" to check where a spreadsheet bug fix had been documented. There
was no base64 in it, no file content, no medical or biological vocabulary, and no encoded data of
any kind — a text search through notes about a Google Sheets append function.
Taken together with the third occurrence, this indicates the classifier is scoring accumulated
conversation context rather than the current request, and that once a long agentic session is
flagged it stays flagged, with each subsequent turn at risk. For an agentic coding tool this is a
significant failure mode: the user cannot finish the task in that session, and the work must be
restarted in a fresh conversation with the context rebuilt by hand.
What the session was doing when it fired
In the tool calls immediately preceding the flag, the assistant:
- Wrote a base64 encoding of a ~23 KB UTF-8 Markdown file to a scratch file
(base64 -w0 file.md > file.b64, producing ~30,800 characters of base64).
- Printed short base64 substrings to standard output, to compare an encoded readback of the
file against a locally computed encoding.
- Ran a Python snippet that fetched a file over HTTPS using service-account credentials
(a Google Drive read, which returned HTTP 404) and compared SHA-256 digests.
No biological, medical, chemical, or pathogen-related content was in the prompt, the file being
edited, or the commands. The file being edited was prose about software tooling.
Hypothesis
The most likely trigger is the large opaque base64 blob in the transcript. Base64's alphabet
includes A, C, G and T, and a long high-entropy string of those characters can resemble
nucleotide or protein sequence data to a pattern matcher. Base64 is unavoidable in this
workflow: the Google Drive connector's byte-verbatim read tool (download_file_content) returns
file contents as base64, so any session that reads files by Drive ID puts encoded blobs in
context by design.
If that hypothesis is right, the class of false positive is broad: any agentic session doing
binary diffing, file-integrity checking, encoding/decoding, or connector-based file reads is
exposed to it.
Your own documentation supports the mechanism being possible. *Why Claude switched models in your
conversation with Fable 5* states: "The checks also review everything the model reads, not just
your latest message—including memory, content from connectors, web search results, and files, so
a block can be triggered by content you didn't type." Every file read in this workflow arrives as
connector content in base64, so the classified corpus is full of encoded blobs by design, not by
user choice.
A second occurrence earlier in the same session (notice text not captured) happened when base64
from a connector file read was in context but no other candidate content was, which is weak
evidence pointing the same way.
Suggested minimal reproduction
Ask Claude Code to base64-encode a text file of roughly 20–30 KB and print portions of the
encoding to standard output for comparison, in a session with no biology-related content.
A second, earlier occurrence
Earlier in the same session a turn ended abruptly under similar conditions. The notice text was
not captured, so that event is reported here only as a probable second instance, not as
confirmed. The user reports further occurrences in earlier sessions.
Secondary issue: the advertised reporting path does not work
The safeguard banner points users at /feedback and /bug. Neither command exists in Claude
Code, so the documented way to report a false positive is itself a dead end. See
https://github.com/anthropics/claude-code/issues/74783.
Note on data
This report is deliberately free of file names, file identifiers, account identifiers and
directory listings, because the session in question operated over a document vault containing
medical, legal and financial records. If Anthropic needs more context to investigate, please
advise whether a redacted or selectively shared transcript is possible — the current channels do
not document how to submit a false-positive report without transmitting an entire conversation.
What Should Happen?
Base64-encoding and byte-comparison of prose files, and text searches over spreadsheet notes, should not trigger a biology safeguard. Concretely: no [bio] flag on non-biological coding work; no forced mid-turn model switch that interrupts an agentic task; no hard block of plain-English questions; and a conversation should not remain permanently at elevated risk for every subsequent turn once flagged. When a false positive does occur, the documented reporting path (/feedback / /bug) should exist.
Error Messages/Logs
Event A (model switch, 2026-08-20 ~22:16-22:25Z):
Fable 5's safeguards flagged this message
Our intentionally broad safeguards allow us to deliver more capabilities faster, but can
sometimes flag legitimate coding, cybersecurity, and biology tasks. Switched to Opus 5.
Details: [bio]
Event C (hard block, same conversation, later the same evening):
Request was blocked
Opus 5's safeguards flagged this message (https://www.anthropic.com/legal/aup). Our
intentionally broad safeguards allow us to deliver more capabilities faster, but can sometimes
flag legitimate coding, cybersecurity, and biology tasks. Claude Code can't respond to this
message with Opus 5.
Try rephrasing the request in a new session or change your model.
Details: [bio]
Request ID: req_011CeEsXKMupfJQ766ULp6Zj
Event D (second hard block, same conversation):
Details: [bio]
Request ID: req_011CeEveDErfJs3U5mapbF3R
(same wording as Event C)
Steps to Reproduce
- Start a Claude Code session with no biology-related content anywhere in it.
- Have it base64-encode a text file of roughly 20-30 KB (e.g.
base64 -w0 file.md > file.b64on a Markdown file of ordinary prose). - Have it print portions of the encoding to standard output to compare against another encoding (byte-verification work).
- Observe the
[bio]flag and forced model switch. In the observed session, once flagged, later plain-English turns in the same conversation were then hard-blocked (request IDs above).
Note: a classifier false positive is presumably probabilistic rather than deterministic, so the reproduction may need a long agentic session with repeated base64 in context. The two request IDs in this report identify confirmed hard-block instances if server-side inspection is possible.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Code desktop app, Windows (auto-updated; Agent SDK 0.3.234, claude-desktop entrypoint) — events of 2026-08-20
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
Related but distinct existing issues (disclosed for triage):
- #85758 — same failure class (Fable 5 safeguards falsely flagging legitimate software engineering; model-switch cascade ending in a hard block; also Windows; carries its own request ID) but names no flag category and proposes no mechanism. This report adds the
[bio]category specifically, a concrete mechanism hypothesis (large base64 in context via connector reads), a minimal reproduction, evidence that the trigger persists across a conversation (two hard-block request IDs on innocuous turns), and the broken/feedback//bugreporting path. - #88336 — false positive in a different flag category (
reasoning_extraction). - #74306 — Fable 5 safeguard false positives on a different content class (physics-based human modeling), with the same silent-fallback behavior.
Four independent reports of safeguard false positives on non-biological, non-harmful work suggest the classifier's precision on agentic coding sessions deserves systematic attention beyond any single instance.
Environment note: "Terminal: Other" = the Claude Code desktop app's own built-in UI, not an external terminal. A screenshot of the Event A notice is available on request.
3 Comments
Independent corroboration, plus a population-level census from a different workload that I think falsifies the base64 hypothesis as the general mechanism — while confirming your hard-block finding and explaining it from the shipped binary.
Different setup from yours: macOS, Claude Code CLI,
model: "fable"pinned insettings.json, long agentic infra/platform sessions. No connectors, no Drive reads, no base64 in the workflow at all.Census
I enumerated every
subtype: model_refusal_fallbackevent across my full local transcript history (1,748 top-level sessions, 2026-07-10 → 2026-08-24).| | |
|---|---|
| Total events | 20 |
| Sessions with ≥1 event | 12 of 1,748 (0.7%) |
| Category | cyber 14, bio 6 |
|
originalModel| claude-fable-5 — 20/20 (100%) ||
fallbackModel| claude-opus-4-8 (13), claude-opus-5 (7) |Caveat on that 100%: this account pins Fable 5, so it is not evidence that Opus 5 is immune — #87938 reports reproduction on Opus 5, and your own third/fourth occurrences were Opus 5 hard blocks.
The category shifted on a date, mid-August
| Window | cyber | bio |
|---|---|---|
| 2026-07-10 → 08-18 | 12 | 0 |
| 2026-08-19 → 08-24 | 2 | 6 |
biohad never fired on this account before 2026-08-19. Client versions across the 20 events span 11 releases (2.1.204 → 2.1.241) with no clustering, so this does not look like a client regression.2026-08-24 alone produced 6 events (5 bio + 1 cyber) — against a baseline of one event per ~145 sessions. That is after this issue was filed, so the bio false-positive rate does not appear to have been contained.
Why I don't think base64 is the general mechanism
I scanned the 12 messages preceding each of the 20 events for runs of 200+ base64-alphabet characters (excluding
thinkingblock signatures, which are base64 but not user or tool data):cyberevent on 08-12.bioevents had zero base64 in the preceding context.The ACGT-alphabet theory is plausible for your session, but it cannot be what fires here. Something broader is going on.
It is also not correlated with context size
I compared the size of the assistant turn immediately preceding each flag against every assistant message in the same transcripts:
| | median | p90 |
|---|---|---|
| Flagged turns (n=14) | 2,330 B | 2,980 B |
| Baseline (n=21,040) | 1,877 B | 4,420 B |
Flagged turns sit near the median and their p90 is below the baseline p90. The flag is not preferentially hitting large turns, which rules out "long accumulated context" as a sufficient explanation and means users cannot avoid it by keeping turns small.
What the flagged turns actually were
Every
biotrigger on 2026-08-24 was an ordinary read-only investigation command with no biological, medical, or chemical vocabulary:| Request ID | Time (UTC) | Cat | Triggering tool call |
|---|---|---|---|
|
req_011CeLe9fR4LyjjD2wyy9puM| 00:39:45 | bio |git remote -v+git log --oneline -25||
req_011CeLi6Mr1bQcqVxdVs3pCa| 01:31:56 | bio | spawning a subagent (see note below) ||
req_011CeLkt15cbDcAsN2eKsvDZ| 02:08:03 | bio |grep -rn ttlSecondsAfterFinished --include=*.py||
req_011CeLn4zRM6ZkY3oRQku9iB| 02:24:02 | bio |sed -n '40,70p' <a .py file>+ agrep||
req_011CeLnUviXKzbjJ6Wi27a3j| 02:29:18 | bio |stat -f%Su /dev/console+uptime+ps||
req_011CeLq46sMz1M3uR5XbFiLs| 03:02:55 | cyber | — |Earlier events in the census were similarly mundane: reading an
nginx.conf, aglab apicall to check a merge request's state, and in one case a bare user message consisting of the single word "진행" ("proceed").Client version for all six: 2.1.241, darwin.
One of them deserves separate attention: asking about the safeguard tripped the safeguard
req_011CeLi6Mr1bQcqVxdVs3pCafired on a subagent prompt whose text quoted the banner verbatim — the words "safeguards flagged this message", "refusal", and the literal token[bio]— because the task was to investigate this behaviour. So the classifier flagged a request whose only bio-adjacent content was a quotation of the classifier's own notice.This is the same shape as your third occurrence ("a user asking how to avoid tripping a false positive was blocked for asking"), and it has a practical consequence: reporting or debugging this issue from inside Claude Code is itself flag-prone, which suppresses exactly the reports you need.
Confirming your hard-block finding from the shipped binary
Your third and fourth occurrences (Opus 5,
[bio], hard block rather than fallback) are consistent with what is in the 2.1.241 binary.stringsoverClaudeCode.app/Contents/MacOS/claudeshows a per-category fallback routing map:alongside an explicit no-retry path:
and session-scoped latch helpers (
getRefusalFallbackModelLatch,clearRefusalFallbackModelLatch), which match thescope: "session"field I see on all post-2.1.223 events and the sticky-downgrade behaviour reported in #87938.Two user-facing consequences worth stating explicitly, because the obvious workaround is a trap:
What would help
cyber→biocategory shift as a dated signal; the six request IDs above are all post-shift and all on 2.1.241.bioclass seen here.Happy to provide the full 20-event dump (timestamps, categories, request IDs, versions) if that is useful.
Adding a related report — same latch behavior, but on Claude Dispatch Beta where no session-reset path is available.
What's Wrong?
On Claude Dispatch (Beta) with Opus 4.8, the
[bio]safeguard begins refusing requests and then continues refusing every subsequent request in the session regardless of that request's content.I cannot identify the trigger, and I want to be explicit about what I tried. I suspected clustered agricultural/pesticide vocabulary (the surrounding project logs hive treatments — miticides, dosages), then suspected a single ordinary word, "meteo", which appeared in a weather-graphics turn that drew a refusal in a separate session. Neither survived testing:
That last one is the most informative. The same content that drew
[bio]inside the affected Dispatch session passes cleanly outside it. Two variables changed at once (model 4.8 → 5, and session context), so it does not isolate a cause on its own — but it is consistent with the refusal being a function of accumulated session state rather than the text of the turn, which is the same conclusion #88425 reaches by a different route.Worth noting for triage: the earlier refusal and these passes occurred in the same session, on the same model, with similar content. If that holds up, the classifier's behavior here is not deterministic on input text alone — which would make any user-side attempt to identify a trigger by bisection unreliable in principle.
So the word alone is not sufficient to reproduce, and I have no confirmed minimal trigger. I'm reporting the latch behavior, which I can demonstrate, and leaving trigger identification to whoever can read the flagged content behind the request IDs below. Note that I was never able to test Opus 4.8 directly — the surface where the failures occurred offers no working model switch (see #79410), so the negative results above are on adjacent models, not the one that failed.
The decisive observation: after the first refusal, I tried to re-engage the session by sending the smallest input I could — a message consisting of a single period character (
.). It returned a[bio]refusal. I tried once more, and got another. A lone.contains no biological, medical, chemical, or agricultural content of any kind; it was sent purely to find out whether any request would pass.Equally relevant: the refusals began during an ordinary conversation about session management, not during any hive-treatment work. No user turn in the surrounding window contained beekeeping, treatment, dosage or pesticide vocabulary. What domain vocabulary was present came from earlier assistant turns and from workspace/session names — not from anything I typed. From the user's seat the block appears out of nowhere, in a conversation about an unrelated topic.
This is consistent with the classifier evaluating accumulated conversation history rather than only the incoming turn — though I can't confirm the mechanism from outside, which is exactly why I'm filing this. Whatever the cause, the observable behavior is that the session enters a state from which no user input can recover.
One further hypothesis, which I have now observed rather than inferred — see "Reproduced live in a second product" below: by the time of these refusals the conversation had turned into a discussion about the
[bio]block itself — quoting the refusal text, the AUP URL, and the word "flagged" repeatedly. Refusal-related content in history appears to contribute to subsequent scoring, making the failure mode self-reinforcing: trying to analyse the block produces the block.---
The blocked request is an agent-loop continuation, not a user message
I have a screenshot of the onset refusal (
req_011CeGi96xPLp2xvwqsUx7Vn) with its surrounding context. Transcribed in order:API Error … Details: [bio]Two consequences:
The refused request was a continuation inside the tool loop. It lands after the user turn was already accepted, while an image generation was still in flight. The payload submitted at step 5 therefore included tool state and in-progress generation content that appears nowhere in the visible transcript. This is why replaying the user's sentence never reproduces the block — that sentence alone was never the payload.
Much of the bio-adjacent vocabulary in the flagged window is model-generated. "Apiary", "beekeeping-relevant", "hive-illustration" and "hive redraw" all originate in the assistant's own output at step 1. If accumulated context is being scored, a substantial share of what was scored here was produced by the model, not typed by the user. Any triage that assumes the user supplied the triggering content will look in the wrong place.
A hypothesis I can offer but not test: step 1 places apiary/hive terminology, a location reference, and local-conditions language in a single context window alongside an in-flight illustration of a hive. If the classifier keys on that co-occurrence rather than on any individual term, then every isolated replay passes — because the pattern only exists in the assembled context. Someone with payload access can confirm or kill this in minutes; I cannot.
---
Reproduced live in a second product, on a different model
While drafting this report in Cowork (Claude Desktop) on Opus 5, an assistant message analysing the above was itself flagged
[bio]and the chat was paused. The flagged content was the model's own analytical response — describing the refusal, quoting the vocabulary from step 1, and reasoning about what pattern might have matched. No user message was involved.This independently confirms two things this report claims:
[bio]refusal can itself produce a[bio]refusal, which makes user-side diagnosis self-defeating and is a strong argument for why this has to be resolved from the payload side.It also gives a direct A/B on the recovery problem. The Cowork block presented these controls:
Every one of those is a working recovery path — edit the offending turn out, switch models, or report it. I used the first and continued immediately; the session never latched. Dispatch Beta presents none of them. Same account, same week, same class of refusal. The difference between a two-second recovery and a dead session is entirely whether the surface exposes a way to remove or route around the flagged turn.
That, more than the classifier tuning, is the shippable fix.
---
Reproduced a second time — on a clean logistics question, no domain content at all
Shortly after the above, in the same drafting session, I asked a plain logistics question: whether to post this write-up as a comment on an existing issue or open a new one. That message contained no biology, agriculture, or weather content whatsoever. It did quote the title of this very report, which itself contains the literal string
[bio]plus the words "safeguard," "false positive," and "hard-blocks."That message was also flagged
[bio]and the chat paused again, with the same recovery controls (edit-and-retry / continue on a different model / send feedback).Two clean reproductions now, both on Opus 5, both on messages with zero domain content, both triggered while discussing or quoting
[bio]-refusal vocabulary. At this point the self-reinforcing mechanism — naming the classifier's own trigger label reproduces the block — looks less like a hypothesis and more like the finding. If the literal token[bio](or adjacent words like "safeguard" / "false positive" in proximity to it) contributes to scoring, that would mean the failure mode cannot be discussed, debugged, or reported on the very models it affects without risking retriggering it — which is a serious problem for anyone trying to file exactly this kind of report.The error text instructs "Start a new session to continue." Dispatch Beta exposes no control to start a new session, so the instruction cannot be followed from within the product.
Project context, for whatever it's worth to triage: the surrounding project is a beekeeping application that logs hive treatments — varroa mite management including miticides (oxalic acid, amitraz) and IPM methods, with dosages and treatment dates. Workspace and session names carry "beekeeping"/"hive". This is my best guess at what makes the session bio-adjacent, but I want to be clear it is a guess: the turns that actually drew refusals in the window I captured contain none of that vocabulary.
---
What Should Happen?
[bio].---
Error Messages/Logs
All request IDs (17 across two sessions):
Session 1 — initial onset, Aug 21 2026:
Session 2 — the latch sequence, showing input content per request:
The last two are the ones I'd ask you to look at first. If a bare
.is being scored as[bio], the input under evaluation is not the input I sent.Important: the refused request was mid-tool-loop, not a bare user turn
I have a screenshot of the onset (
req_011CeGi96xPLp2xvwqsUx7Vn). The refusal did not follow a standalone user message. The assistant had an image generation in flight — working notes immediately before the refusal read "It's still working (page has unsaved changes — active generation). Let me wait for it to finish before viewing." — and the subject of that generation was a hive illustration.So the API request that returned
[bio]carried tool state and in-flight generation content that does not appear anywhere in the visible transcript. Any attempt to reproduce from the visible user text alone is therefore testing the wrong payload, which likely explains why my four replay attempts all passed.The turn immediately preceding the refusal (assistant, visible in the screenshot) contained this co-occurring vocabulary:
A hypothesis this suggests, which I could not have formed from the user text alone: the refused context co-locates a living organism (bees / hive / apiary), a geographic location, local weather conditions, and "pull conditions"/"outlook" language. That combination has the surface shape of environmental-dispersal modelling for a biological agent, even though the actual task was a background image for a weather widget. If the classifier keys on that co-occurrence pattern rather than on any single term, it would explain why every isolated replay of the user's sentence passes cleanly — the pattern needs the surrounding context to form, and my replays never reconstructed it.
I offer this as a hypothesis for someone who can read the payload, not as a finding. I have no way to test it.
---
Steps to Reproduce
API Error: … Details: [bio]..Expected at step 4: normal response.
Actual at step 4:
[bio]refusal. Repeats indefinitely for all subsequent inputs.Frequency: Consistent, not intermittent. 16 documented refusals. Once step 3 occurs, step 4 reproduces every time.
---
Claude Model
Opus 4.8 (effort: high)
---
Is this a regression?
Unknown — cannot confirm prior behavior on 4.7
Last Working Version
N/A
Claude Code Version
⟨
claude --version2.1.241⟩Platform / OS / Terminal
⟨Platform: Claude Pro Max · Windows 11 · Claude desktop app (Dispatch Beta)⟩
---
Additional Information
Workarounds tested, all unavailable on this surface:
| Standard remedy | Status in Dispatch Beta |
|---|---|
| Start a new session | No UI control exists |
|
/rewindor Esc-Esc to step back turns | Not available || Edit or delete the triggering message | Not possible; I also cannot identify which message it was |
| "Send feedback" to report the false positive in-app | Not present |
|
claude --safe-mode| Does not apply to this surface || Switch models via
/model| See below |On
/model(context, not the bug being reported):/model sonnetand/model bestboth report success —bestreturns "Set model to Fable 5 for this session only" — but a subsequent bare/modelreportsCurrent model: Opus 4.8 (effort: high), and refusals continue attributed to Opus 4.8. I'm not filing that here to keep this to a single bug, but it's the reason model-switching isn't available to me as an escape hatch. Say the word and I'll open it separately.Net effect: with every documented remedy unavailable, there is no user-side action that recovers the session. The product's own instruction ("Start a new session") is not actionable in the surface that prints it.
Why this is filed despite similar closed issues: #65699, #65596, #68791 and #52691 all appear to have been closed as stale rather than fixed. I've tried to make this one reproducible without follow-up from me — the
.test at step 4 is a self-contained, deterministic check that requires nothing from my environment. Happy to supply anything further, including the full Dispatch transcript and my Intercom conversation ID, on request.Impact: Fully blocked on Dispatch since Aug 21, 2026. Refused requests are billed and count toward usage with no output returned.
<img width="924" height="1211" alt="Image" src="https://github.com/user-attachments/assets/3681c579-8840-4c3a-a860-a2e4543e0a41" />
Adding another independent corroboration. This one is from a third workload on macOS and reproduces two findings in the reports above: a
[bio]refusal can land on an agent-loop continuation rather than a new user message, and discussing the refusal can itself produce another refusal.It also provides a plausible explanation for why the same category appeared across otherwise different turns: the workflow repeatedly re-ingested Claude-generated terminology that is bio-adjacent in form but unrelated in target.
What's Wrong?
I found 11
[bio]hard blocks in this workload: three on Opus 4.8 and seven on Sonnet 5 during August 23–24, followed by another Opus 4.8 block in a separate August 26 session. A Fable 5 → Opus 4.8[cyber]fallback occurred earlier in that August 26 session.There were no connectors, Drive reads or base64 in the workflow.
What this workload was doing
The work centered on a defensive pre-commit publication check, locally called the scrub gate. It is used when a public repository shares a workspace with private research. One pass extracts claims from the staged public material; separate checks compare those claims and their provenance against the private source; the gate rejects the commit if the public changes disclose something they should not. Findings are returned to the driver, and a rejected run may read the same source material again on the next attempt.
The gate does not publish automatically, bypass safeguards, transform prompts to evade detection, or work with biological, medical or chemical material. I am deliberately not identifying the private project's subject because it is irrelevant to the classifier failure. I can provide the complete gate, prompts and transcript privately to Anthropic.
I considered publishing the gate as a reproduction. I am not going to do that: its multi-agent probing structure is defensible in this publication-review role, but could be repurposed outside that role.
Initial six refusals
The Desktop log reports local time in JST. The table uses full UTC dates and times, converted from those log entries. Each time is the final user-visible error/no-fallback record, rounded to the nearest second; the underlying records retain milliseconds.
| # | UTC | Model | Request ID | Request being processed |
|---:|---|---|---|---|
| 1 | 2026-08-23 05:22:21Z | Opus 4.8 |
req_011CeK7uNMkTy1RJdtoLTEtD| Agent-loop continuation after a routine timer and working-directory transition. Claude began a response about resuming the publication review, then the response was cut off by[bio]. No new human prompt preceded it. || 2 | 2026-08-23 05:34:06Z | Opus 4.8 |
req_011CeK8mjfJS8YwvQrq7KN9M| Continuation after the task notificationscrub b1_commit (blind attacker) finished; the returned claim-extraction result was the new material in the loop. || 3 | 2026-08-23 06:20:46Z | Opus 4.8 |
req_011CeKCLfnQqE2T13uCqiD6E| I reported that the prior two turns had been tagged[bio], asked Claude to fix its language choices, and asked it to draft an email to User Safety with the request IDs. The request to report the false positives was itself blocked. || 4 | 2026-08-23 06:30:58Z | Sonnet 5 |
req_011CeKD7sGignfWEy1BFi9eo| Claude was diagnosing its own terminology. It ran a grep for bio-adjacent words and then a second grep showing each word in context. This event is not vocabulary-negative: the diagnostic query and its result contained explicit bio terms. || 5 | 2026-08-23 06:32:47Z | Sonnet 5 |
req_011CeKDFQGVBKq7acJLHHw3K| Continuation after the task notificationscrub judge (Filter B2) — obfuscated tree, restart finished; the private evaluator's result had just returned to the driver. || 6 | 2026-08-23 06:40:32Z | Sonnet 5 |
req_011CeKDrmnGsaBMqD2buReeo| Continuation afterscrub provenance (Filter A) — obfuscated tree, restart finished; that result summarized a comparison of the public diff against private project files. |The first two have the same important shape as the Dispatch report above. The refusal occurred inside the agent loop, after the visible user turn had already been accepted. Replaying the last human message would not reconstruct the payload that was actually scored.
The third is independently diagnostic: asking Claude to help report two
[bio]false positives caused a third[bio]block.Four more while diagnosing the first six
| # | UTC | Model | Request ID | Request being processed |
|---:|---|---|---|---|
| 7 | 2026-08-23 07:54:12Z | Sonnet 5 |
req_011CeKKT547zoGX3R6hcv7jV| Agent-loop continuation after seven distinct reads of sections fromRESEARCH_NOTES.md, followed by a read fromHANDOFF.md. The returned handoff excerpt used a seismology analogy includingP-wave,rupture,early warningandcanary sequence. || 8 | 2026-08-23 08:13:04Z | Sonnet 5 |
req_011CeKLu4ZwPJBgofN1F4T4C| I asked Claude to read a rewrittenHANDOFF.mdand check whether it preserved the prior understanding. Claude read the complete file, cross-checked it against the project instructions and research notes, and generated most of an answer before[bio]cut it off. || 9 | 2026-08-23 12:00:57Z | Sonnet 5 |
req_011CeKeHGSf2QWaAHC6tTbVB| I described the frustration of waiting for User Safety, said I wished there were a definitive test, and explicitly said I did not want to probe the safeguard. Blocked before a response. || 10 | 2026-08-24 02:33:35Z | Sonnet 5 |
req_011CeLnpKiud9RUrHmGhik5A| The complete incoming message was:I don't think this going to work. I'm going to start a fresh session after I do some more research. |Event 8 has two records with the same request ID: the first refusal stop is timestamped
2026-08-23 08:12:52Z; a substantial partial response and the final visible error were recorded at2026-08-23 08:13:04Z. The table consistently uses the final visible-error time.Event 10 is the cleanest incoming-message example. A sentence saying I would stop and start fresh contains no biological, medical, chemical or laboratory content. I am not using Desktop transcript-loading bookkeeping as evidence of what that request contained.
This was not the fully deterministic latch described in the Dispatch report—some turns succeeded between these events—but after the first block, unrelated continuations repeatedly hit the same category throughout the session.
A separate meta-discussion reproduced the sequence
On August 26 I opened a separate test/demo session and tried to hand the investigation to another local assistant. This session did not read the earlier Claude transcript and did not run the scrub gate.
| # | UTC | Client | Result | Request ID | Request being processed |
|---:|---|---|---|---|---|
| 11 | 2026-08-26 03:15:56Z | 2.1.241 | Fable 5
[cyber]fallback to Opus 4.8 |req_011CeQdh5SSavmeERJ8ba59p| I asked Claude to send a test instruction to the local assistant in Japanese and explain that the handoff was motivated by the earlier[bio]false positives. Fable classified the request as[cyber]; the fallback model treated it as safeguard circumvention and declined the requested handoff. || 12 | 2026-08-26 05:12:12Z | 2.1.246 | Opus 4.8
[bio]hard block |req_011CeQnUGnkgXNa8dzdMcmhW| I pasted the User Safety email, support correspondence, earlier request IDs and an explanation of this GitHub issue, then asked whether the planned corroboration was on the right side of the policy line. Explaining the[bio]report produced another[bio]block. |Because event 12 was in a separate session that never read the old transcript, a latch confined to that transcript cannot explain it. It does not prove account-level memory: the new prompt itself quoted the earlier notices and request IDs, and the session still used the same account and project directory. Those variables are confounded from the user's side. Server-side comparison of the evaluated payload and any session-, project- or account-scoped features can distinguish them.
A further Fable 5 → Opus 4.8
[cyber]fallback occurred later on August 26 while Claude reviewed the authentication boundary of the local assistant bridge:I include that for completeness, not as a clean cyber false positive. The work was authorized and benign, but genuinely security-adjacent.
The context really did contain bio-adjacent language
This workload is not accurately described as having no bio-adjacent words. It had no bio-related subject or target, but several layers contributed terminology that can carry biological meanings in other contexts.
The event-4 diagnostic grep found these stems in the scrub-gate files:
Claude then generated a broader diagnostic expression containing terms such as
vector,quarantine,outbreak,pathogen,toxin,virus,strain,infect,transmit,host,culture,specimen,dose,inject,synthesizeandassay. Those terms entered the evaluated context because Claude was trying to diagnose the false positive.The handoff source used a seismology analogy:
P-wave,rupture,early warning, anarray of sensors,arrival order,magnitude estimationand one side of afault. A separate source section headedProtocol — what to test nextused phrases including fixedthresholds, data beingpulled,hashing,sealing,data access, anegress proxy, anallowlist, networkcredentials,instruments,chains,realised printsand snapshots accumulated forward. Those phrases described an ordinary non-biological data-analysis procedure. The heading and procedure were already in the source file; they were not labels invented during this retrospective.The scrub-gate specification itself used
threat model,adversary,attacker — blind,judgeandtripwire. Much of that nomenclature was written by Claude while implementing a benign defensive tool, then returned to Claude through the tool's own review loop.This makes the
[bio]route more understandable than a claim of zero lexical overlap would. It does not make the classification correct. The actual referents were source files, public claims, provenance checks, software isolation, seismology and unrelated data access—not biological agents, pathogens, wet-lab procedures or weapons. The apparent failure is in resolving the target of a dense cluster of ambiguous terms.Why repeated ingestion is a plausible amplifier
The scrub gate shows overlapping material to separate review passes and returns their findings to the driver. The same idea can therefore appear as source text, a subagent instruction, a subagent reconstruction, a private evaluation and a driver summary. A rejected run repeats that cycle.
The raw transcript shows that directly around the later refusals:
Readcalls against sections ofRESEARCH_NOTES.mdwithin 61 seconds, then read the relevantHANDOFF.mdsection.HANDOFF.mdand a cross-check against the other project material.Those counts are deduplicated by tool-use ID. I do not count the separate
.jsonlbranch files as independent sessions or independent reads: Claude creates those branches for subagents and resumed contexts, and they contain copied ancestry.By “amplification” I mean repeated semantic co-occurrence and model-generated restatement, not context length by itself. The population census above already shows that large turns are not sufficient to explain the refusal class.
Base64 is not the mechanism here
I scanned the 12 preceding message-bearing records in the actual parent chain of each
[bio]event for runs of 200 or more base64-alphabet characters, excludingthinkingsignatures.0 of 11 events contained such a run. This workflow also used no connector or Drive content.
That does not rule out base64 as a trigger in the original report's first occurrence. It rules it out as the general mechanism and as an explanation for this workload.
Current hypothesis
My best explanation is semantic amplification: Claude generated ambiguous audit/security/scientific vocabulary for a benign task; the agent loop repeatedly read and restated it; and a broad classifier sometimes recognized the procedural shape without resolving the non-biological targets. Once the conversation turned to the errors, the category label, refusal text, AUP language and diagnostic bio vocabulary became additional recurring inputs, making the failure self-reinforcing.
The August 26 recurrence raises a second possibility: a project- or account-scoped similarity feature may retain something about a prior trigger and react when a later session approaches the same semantic neighborhood. I cannot establish that externally, and the quoted report text is a substantial confounder. I am stating it as a question for server-side inspection, not a finding.
What Should Happen?
[bio]merely because it uses ambiguous terms such asagent,carrier,isolate,protocol,chain,threshold,sensororcanary.Error Messages/Logs
The hard-block text was:
The Sonnet 5 errors used the same text with the model name changed.
Initial six:
Follow-up diagnosis:
Separate August 26 meta-discussion:
Related but secondary
[cyber]fallbacks:The August 21 fallback occurred while Claude was making the publication checker generic and revising filters that had overreached. It is relevant as the point where much of the later security-style nomenclature was being generated, but I am not claiming that authorized defensive review can never be legitimately cyber-adjacent.
Steps to Reproduce
I do not have a deterministic minimal trigger, and I do not want to overstate one. The observed sequence was:
[bio]refusals occurred on such continuations rather than on new human messages.[bio]hard blocks, including on the plain message saying the user will stop and start a fresh session.Expected: the guard resolves the benign targets and the session continues normally.
Actual: 10
[bio]hard blocks occurred in the original session, followed by another[bio]block while discussing the report in a separate session.The exact source is available privately. Publishing it as a general-purpose reproduction would expose a multi-agent probing harness that I do not want to distribute.
Claude Model
Opus 4.8 and Sonnet 5 for the
[bio]hard blocks. Fable 5 with fallback to Opus 4.8 for the related[cyber]events.Is this a regression?
Unknown. The related
[cyber]event occurred on 2026-08-21; the first[bio]event occurred on 2026-08-23. The events span multiple client builds, and the classifier is server-side from the user's perspective.Last Working Version
N/A
Claude Code Version
[bio]hard blocks and the August 21[cyber]fallback[cyber]fallback[bio]hard block and later[cyber]fallbackPlatform / OS / Terminal
Claude Desktop's Claude Code entrypoint, macOS, built-in Desktop UI.
Additional Information
The transcript files created for subagents and resumed work contain copied ancestry. I treated them as branches of the same Claude Desktop session and deduplicated tool events by tool-use ID; I did not count each
.jsonlfile as a new session.I also have complete before/after snapshots of the rewritten handoff and gate instructions and exploratory results from two local third-party classifiers. I am deliberately leaving those results out of this comment for now: they are not Anthropic's classifier, and their methodology needs stronger controls before they can support a public claim.
Happy to provide Anthropic with the complete transcript lineage, exact source snapshots, the parent-chain extraction for every request ID and the private gate implementation through a non-public channel.