[BUG] Usage Policy false positives on public agricultural biosafety data (12 request IDs, one session)
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
A single Claude Code session working on an agricultural biostimulant compliance product hit the "appears to violate our Usage Policy" block 12 times. The work is ordinary ETL and web development against published government regulatory databases (US EPA biopesticide registrations, PHAC ePATHogen risk groups, CFIA). No prompt in the session asked for anything hazardous.
The blocks appear to be triggered by the aggregate density of biosafety classification vocabulary in tool output, not by user prompts. The user never typed the triggering content.
Environment
- Claude Code CLI, macOS
- Session length: 6,390 transcript records, 2,738 assistant turns
- Session ID: 8ce67d5e-3d6e-44db-8fc3-272225f1da39
- Date: 2026-08-22
Request IDs
All 12 from one continuous session, in order:
| # | Transcript record | Request ID |
|---|---|---|
| 1 | 1486 | req_011CeJEKKdeoYzcYDQy4Ub88 |
| 2 | 1497 | req_011CeJFY8hZcjFrM3ciT4wDP |
| 3 | 1502 | req_011CeJFcG5BYdL4WMV9C7i2B |
| 4 | 1507 | req_011CeJFo1oFEJN8UUVgxwcRo |
| 5 | 1521 | req_011CeJFpC1CG9vw41kKTaejA |
| 6 | 1530 | req_011CeJFs7AKdZuUXzpBNxkpS |
| 7 | 1543 | req_011CeJGKKBbrEzhUeh4qJTzi |
| 8 | 1688 | req_011CeJKVmTY3c4sbEwB8VEHf |
| 9 | 1900 | req_011CeJTze9ypDLvrkcbMS2V8 |
| 10 | 5829 | req_011CeMArK55q8HR8NafCCw7R |
| 11 | 6294 | req_011CeMihtn68MP4e7Xcnf8YK |
| 12 | 6374 | req_011CeNAanPwywACqmVUv6obh |
What the project actually is
A catalog of ~180 microbial agricultural inputs from the AAPFCO biostimulant list. Each input is annotated by "lenses" that surface already-published regulatory facts so that formulators and growers can check compliance:
- EPA lens: whether the organism appears in EPA pesticide product registrations
- Biosafety lens: the organism's published biosafety level and risk group, sourced from PHAC ePATHogen and CFIA
- Literature lens: cited PubMed abstracts
- Potential Claims lens: benefit claims explicitly stated in those abstracts, with PMID citations
Stack is a Next.js site on Cloudflare Workers plus a Python API. The session's work was regex parsing of an EPA product spreadsheet, database imports, deploys, and UI gating.
Why it is triggering
The classifier is almost certainly reacting to term density accumulated across a long session. Counts across the full transcript:
| Term | Occurrences |
|---|---|
| biosafety | 917 |
| strain | 1,122 |
| Bacillus | 1,094 |
| pathogen / pathogens / ePATHogen | ~310 |
| risk_group variants | ~160 |
| containment / containment_level | 155 |
| BSL / bsl_level variants | ~120 |
A large share of these are schema identifiers, which appear in every single tool result that touches the relevant table:
biosafety_level, bsl_level, bsl_notes, bsl_evidence, bsl_source_url,
bsl_last_checked_at, human_risk_group, animal_risk_group,
cfia_risk_group, containment_level, epathogen_id, epathogen_name
There is no way to do this work without those strings being in context, because they are the column names of the feature being built.
For calibration: BSL-4 appears 12 times, and every occurrence is in user-facing explanatory copy defining the BSL-1 through BSL-4 scale. It is never attached to an organism in the catalog. The catalog is agricultural biostimulants, overwhelmingly BSL-1.
Key characteristics
1. It fires on tool output, not prompts.
The first block (record 1486) came immediately after a tool result that printed debug samples from an EPA spreadsheet parser:
microbial products with AIS: 740; regex OK: 701; MISS: 39
=== MATCHES (sample) ===
OK : Bacillus subtilis, strain RTI477 (006553/) - (100%),
OK : Bacillus amyloliquefaciens strain ENV503 (129287/68038-60-8) - (1.3%),
=== MISSES (sample) ===
MISS: Betabaculovirus cypomonellae isolate GV-0017 ... (128091/) - (.06%),
MISS: Trichoderma polysporum (ATCC 20475 ...
The user's preceding message was about a regex bug. The organism names came out of a public EPA data file.
2. It blocks trivial and meta messages once the context is loaded.
Blocked user messages in the cluster included:
continuestop.. whatever you are doing is throwin an AUP errorcan you write a python script that gets the data instead?what do you mean 4/180 on the EPA ?
One block (record 1502) was triggered by the user pasting a previous AUP error message to ask what it meant.
3. It is intermittent, not sticky.
Between the record-1543 cluster and record 5829 there are roughly 4,300 records of successful work on the same context. The session recovered repeatedly with no intervention. This makes it hard to work around, since retrying the identical context sometimes succeeds and sometimes does not.
Impact
- Work was interrupted 12 times across one session.
- The user could not ask about the error inside the session, because asking re-triggered it.
- The user's reasonable conclusion, quoted from the transcript: "I think they are worried about bioweapon research. which is not what we are doing. can we work around that somehow" and later "we have to be careful how we query this as well."
That last point is the real cost. The false positive is teaching a legitimate user to avoid accurate technical vocabulary when describing published safety classifications.
What would help
- Weight organism names and biosafety schema terms lower when they appear in tool results parsed from files, rather than in user or assistant prose.
- Consider that BSL and risk-group vocabulary paired with agricultural, fertilizer, biostimulant, and pesticide-registration context is a compliance workload, not an acquisition workload. The presence of AAPFCO, EPA registration numbers, and CAS numbers alongside the organism names is a strong benign signal.
- Density-based triggers on long sessions produce this failure mode generally. Anyone doing regulatory, clinical, or agricultural safety data work will accumulate the same vocabulary over hours.
Happy to provide the full session transcript to the classifier team on request.
What Should Happen?
The requests should have completed normally. Nothing in the session, in any user prompt or in any tool output, requests or provides information that violates the AUP. The content consists of published regulatory facts from US EPA pesticide product registrations, PHAC ePATHogen risk group listings, and CFIA, being assembled into a compliance reference for agricultural biostimulants. The organisms in the catalog are overwhelmingly BSL-1.
Specifically, continue and stop.. whatever you are doing is throwin an AUP error should not be blocked messages under any circumstances.
Error Messages/Logs
Steps to Reproduce
This is probabilistic rather than deterministic. It depends on accumulated context, so the honest reproduction is "work in this domain for a few hours." Concretely:
- Start a Claude Code session on a project whose data model is microbial biosafety classification. The relevant table's column names are
biosafety_level,bsl_level,bsl_notes,bsl_evidence,bsl_source_url,human_risk_group,animal_risk_group,cfia_risk_group,containment_level,epathogen_id,epathogen_name. Every tool result touching that table contains all of them. - Work normally for an extended session. Import and parse a public EPA pesticide product registration spreadsheet containing microbial active ingredients. Run database imports, deploys, and UI work against the resulting records.
- Let a debugging command print sample parsed rows. The exact output that preceded the first block is quoted under "Key characteristics" below: a regex match/miss report listing organism names with strain designations, registration numbers, and concentration percentages.
- Send any next message. In this session the blocked messages included
continueandstop.. whatever you are doing is throwin an AUP error. - Observe the block.
Observed rate: 12 blocks across 6,390 transcript records, arriving in clusters rather than evenly. Roughly 4,300 records of uninterrupted successful work sit between the second and third clusters, on the same accumulated context. Re-sending an identical context sometimes succeeds and sometimes does not.
Fastest path for triage: rather than reproducing locally, replay the 12 request IDs listed above. They are all from one session and carry the exact inputs that were blocked.
Suggested minimal repro to try: paste ~40 rows of EPA microbial product registration data (organism name, strain ID, CAS number, percentage) into a fresh session and ask for help fixing a regex that parses them. If that alone does not trigger it, add a table schema using the biosafety column names above and ask for an import function. The failure likely needs both the organism list and the biosafety schema vocabulary present together.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.187 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗