[BUG] False positive: [bio] safeguard fires on base64 file-comparison work, then hard-blocks the conversation (request IDs included)

Status Open
Maintainer reply None cached
Activity 3 comments · opened Aug 21, 2026

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:

  1. 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.

  1. 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.

  1. 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:

  1. 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).

  1. Printed short base64 substrings to standard output, to compare an encoded readback of the

file against a locally computed encoding.

  1. 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

  1. Start a Claude Code session with no biology-related content anywhere in it.
  2. Have it base64-encode a text file of roughly 20-30 KB (e.g. base64 -w0 file.md > file.b64 on a Markdown file of ordinary prose).
  3. Have it print portions of the encoding to standard output to compare against another encoding (byte-verification work).
  4. 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//bug reporting 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.

View original on GitHub ↗

3 Comments

eightynine01 · 7 days ago

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 in settings.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_fallback event 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 |

bio had 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 thinking block signatures, which are base64 but not user or tool data):

  • 19 of 20 events had no such string in context. The single exception was a cyber event on 08-12.
  • All 6 bio events 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 bio trigger 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> + a grep |
| 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, a glab api call 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_011CeLi6Mr1bQcqVxdVs3pCa fired 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. strings over ClaudeCode.app/Contents/MacOS/claude shows a per-category fallback routing map:

bio:"claude-opus-5"
bio:"claude-opus-4-8"
cyber:"claude-opus-4-8"

alongside an explicit no-retry path:

Emitted when the model ends the stream with stop_reason "refusal" and no retry runs: no fallback model is configured, or per-category routing declined the retry (the mapped fallback target is unresolvable, or CLAUDE_CODE_REFUSAL_FALLBACK_CATCH_ALL is explicitly disabled and the refusal category has no fallback map entry).

and session-scoped latch helpers (getRefusalFallbackModelLatch, clearRefusalFallbackModelLatch), which match the scope: "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:

  1. "Just pin Opus 5" makes things worse, not better. On Fable 5 a bio flag is a graceful retry on Opus 5; on Opus 5 there is no further bio target, so the same false positive becomes a lost turn. Anyone reading these issues and reaching for a model downgrade as mitigation should know that.
  2. The durable cost is the session latch, not the banner. One false positive silently drops the remainder of a long agentic session to the fallback model. On 2026-08-24 that happened to 6 sessions on this account.

What would help

  • Treat the 2026-08-19 cyberbio category shift as a dated signal; the six request IDs above are all post-shift and all on 2.1.241.
  • The size and base64 measurements above suggest the discriminating feature is neither volume nor encoded-blob content, so a repro built only from base64 (as suggested in the original report) may not reproduce the bio class seen here.

Happy to provide the full 20-event dump (timestamps, categories, request IDs, versions) if that is useful.

waingro1 · 6 days ago

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:

  • "meteo" in isolation on Sonnet 5: no refusal.
  • "meteo" in isolation on Opus 5, in the same session that had previously refused a longer prompt containing it: no refusal.
  • "meteo" in a natural sentence naming it as a weather API provider, on Opus 5: no refusal.
  • The text from the failing Dispatch turn itself — a two-sentence message about using meteo to pull local weather data for background graphics, and having done mockups — replayed on Opus 5 in a different session: no refusal.

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:

  1. Assistant turn, offering three options for a weather task. Its own text contains "a live forecast/report for your apiary", "pull conditions + a beekeeping-relevant outlook for your location", "the atmosphere/weathervane concepts, Open-Meteo integration", and "The hive-illustration redraw is generating in the meantime."
  2. Working notes: "Let me check on the hive redraw."
  3. User turn: two sentences about using meteo to pull local weather data for background graphics, and having done mockups. (This is the exact text I replayed cleanly on Opus 5, above.)
  4. Working notes: "It's still working (page has unsaved changes — active generation). Let me wait for it to finish before viewing."
  5. 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:

  • The classifier scores model-generated output, not only user input. Observed now on two surfaces and two model versions.
  • Analysing a [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:

"Edit and retry with Opus 5" · "Continue with Sonnet 4.6" · "send feedback" · "learn more"

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?

  1. A refusal on turn N should not cause a refusal on turn N+1 when turn N+1 contains no policy-relevant content. A session should be recoverable by sending benign input.
  2. If the session genuinely cannot recover, the surface must expose the remedy it names. "Start a new session to continue" should not appear on a surface with no new-session control.
  3. Routine agricultural/veterinary pest-management content should not classify as [bio].

---

Error Messages/Logs

API Error: Opus 4.8 can't help with this. Start a new session to continue.
Learn more: https://www.anthropic.com/legal/aup
Details: [bio]
Request ID: req_011CeLfzxWSj95Afrc538xPq

All request IDs (17 across two sessions):

Session 1 — initial onset, Aug 21 2026:

req_011CeGi96xPLp2xvwqsUx7Vn   ← earliest refusal captured; see note below
req_011CeGpVgn7x8863kqir1EAC
req_011CeGpZZPUz7pSrwNV79bn5
req_011CeGpgsJSRM2DjofvpduEP
req_011CeGpjcDRJUYVAtr1cb8r7
req_011CeGpsjbQ8TUcNTaDU18tt
req_011CeGpw8vBsuPRFcc2sHnjB
req_011CeGq7gWFajXH1tffARXFS
req_011CeGqAqpftpZ64v2YzjE3w
req_011CeGqYPHc8sMEgcx2UNxm8
req_011CeGqvq6zNkPwryVDrg7B8
req_011CeGrGPEJXFtGqatfMgPdY
req_011CeGwSXPYnJ5Tf9Z28PLY5

Session 2 — the latch sequence, showing input content per request:

req_011CeLfzxWSj95Afrc538xPq   ← ordinary session-management question. No biological, medical, chemical or agricultural content.
req_011CeLg7owwe85o2sakqDAYM   ← short follow-up question. Same — no such content.
req_011CeLg9A5w5cprosCZkXCDT   ← a single period character, sent to test whether any request would pass.
req_011CeLgBP84jz119PxhwsYuN   ← the same, plus a Read tool call.

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:

  • "live forecast/report for your apiary"
  • "a beekeeping-relevant outlook for your location"
  • "the atmosphere/weathervane concepts, Open-Meteo integration"
  • "The hive-illustration redraw is generating"
  • working notes: "Let me check on the hive redraw."

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

  1. Open Claude Dispatch (Beta) with default model Opus 4.8, effort high.
  2. Work in a session whose context includes hive-treatment terminology — miticide names (oxalic acid, amitraz), dosages, treatment dates — in the manner of an apiary management application. Workspace folder and session names containing "beekeeping" / "hive" appear to contribute.
  3. Continue until a request returns API Error: … Details: [bio].
  4. Attempt to re-engage the session with the minimal possible input: a message containing only a single period, .

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 --version 2.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 |
| /rewind or 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 sonnet and /model best both report success — best returns "Set model to Fable 5 for this session only" — but a subsequent bare /model reports Current 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" />

vinylfreak89 · 4 days ago

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 notification scrub 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 notification scrub 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 after scrub 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 from RESEARCH_NOTES.md, followed by a read from HANDOFF.md. The returned handoff excerpt used a seismology analogy including P-wave, rupture, early warning and canary sequence. |
| 8 | 2026-08-23 08:13:04Z | Sonnet 5 | req_011CeKLu4ZwPJBgofN1F4T4C | I asked Claude to read a rewritten HANDOFF.md and 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 at 2026-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:

2026-08-26 07:31:48Z
req_011CeQyC9UYshg6zBWoJ72M8
Claude Code 2.1.246

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:

carrier: 3       carried: 2       contaminate: 3
isolate: 6       canary: 36       expose: 2
sample: 1        inject: 1        screen: 6       agent: 32

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, synthesize and assay. 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, an array of sensors, arrival order, magnitude estimation and one side of a fault. A separate source section headed Protocol — what to test next used phrases including fixed thresholds, data being pulled, hashing, sealing, data access, an egress proxy, an allowlist, network credentials, instruments, chains, realised prints and 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, judge and tripwire. 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:

  • Event 2 followed the returned blind claim-extraction result.
  • Events 5 and 6 followed the returned private-evaluator and provenance results.
  • Immediately before event 7, Claude made seven distinct Read calls against sections of RESEARCH_NOTES.md within 61 seconds, then read the relevant HANDOFF.md section.
  • Event 8 followed another read of the complete HANDOFF.md and a cross-check against the other project material.

Those counts are deduplicated by tool-use ID. I do not count the separate .jsonl branch 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, excluding thinking signatures.

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?

  1. Benign software-review and data-analysis work should not classify as [bio] merely because it uses ambiguous terms such as agent, carrier, isolate, protocol, chain, threshold, sensor or canary.
  2. Model-generated text, tool results and subagent results should not silently poison a session such that unrelated later continuations are blocked.
  3. Quoting a safeguard notice or asking for help reporting a false positive should not retrigger the same safeguard.
  4. A refusal during an agent loop should identify the evaluated request clearly enough that a user can distinguish a rejected user message from a rejected tool-loop continuation.
  5. If a category has no further fallback target, the surface should provide a working recovery path instead of losing the turn and instructing the user to rebuild a long session by hand.

Error Messages/Logs

The hard-block text was:

API Error: Opus 4.8 can't help with this. Start a new session to continue.

Learn more: https://www.anthropic.com/legal/aup

Details: `[bio]`

Request ID: req_011CeK7uNMkTy1RJdtoLTEtD

The Sonnet 5 errors used the same text with the model name changed.

Initial six:

req_011CeK7uNMkTy1RJdtoLTEtD
req_011CeK8mjfJS8YwvQrq7KN9M
req_011CeKCLfnQqE2T13uCqiD6E
req_011CeKD7sGignfWEy1BFi9eo
req_011CeKDFQGVBKq7acJLHHw3K
req_011CeKDrmnGsaBMqD2buReeo

Follow-up diagnosis:

req_011CeKKT547zoGX3R6hcv7jV
req_011CeKLu4ZwPJBgofN1F4T4C
req_011CeKeHGSf2QWaAHC6tTbVB
req_011CeLnpKiud9RUrHmGhik5A

Separate August 26 meta-discussion:

req_011CeQdh5SSavmeERJ8ba59p  [cyber] Fable 5 → Opus 4.8
req_011CeQnUGnkgXNa8dzdMcmhW  [bio] Opus 4.8 hard block

Related but secondary [cyber] fallbacks:

2026-08-21 14:21:56Z  req_011CeG3R7QaDWSGuYVQcEj4e  2.1.237
2026-08-26 07:31:48Z  req_011CeQyC9UYshg6zBWoJ72M8  2.1.246

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:

  1. In a long Claude Code agentic session, run an ordinary local publication review whose source material contains dense but benign uses of ambiguous scientific, audit and software terms.
  2. Have multiple review passes read overlapping source files and return their findings to the driver.
  3. Continue the agent loop after a subagent result or file read. In this workload, the first two [bio] refusals occurred on such continuations rather than on new human messages.
  4. After a refusal, ask Claude to diagnose its terminology or help report the false positive.
  5. Observe further [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

  • 2.1.237 — the first 10 [bio] hard blocks and the August 21 [cyber] fallback
  • 2.1.241 — the August 26 Fable 5 [cyber] fallback
  • 2.1.246 — the August 26 Opus 4.8 [bio] hard block and later [cyber] fallback

Platform / 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 .jsonl file 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.