Safety, Refusals & Fallbacks
In production, your code must handle the case where Claude won't (or can't) answer as expected. Done well, this is invisible to users; done badly, it's a crash or a confusing reply.
- Tell a model refusal apart from a classifier/safety block — and why it matters
- Handle a refusal as a normal outcome instead of crashing or showing an empty reply
- Cut the refusals you didn't want, without trying to jailbreak the ones you did
- Pick a fallback: clarifying question, safe alternative, or human handoff
Two different things
- A model refusal — Claude declines a request (e.g. it judges it harmful). The response signals this (commonly via a refusal
stop_reason/content). Treat it as a normal outcome, not an error. - A classifier/safety block — a separate safety layer may block content. This can look different from a model refusal.
Knowing which you got lets you respond appropriately rather than retrying blindly.
Handle it gracefully
resp = client.messages.create(...)
if getattr(resp, "stop_reason", None) == "refusal":
# Don't show a raw/empty result. Offer a safe fallback or a clarifying ask.
show_user("I can't help with that as asked. Here's what I can do instead…")
else:
render(resp)
Reduce unwanted refusals
- Add legitimate context. A request can pattern-match to something sensitive when intent is benign; stating the real, legitimate purpose helps.
- Be specific. Vague or edgy phrasing invites caution.
- Don't fight it. If a request is genuinely disallowed, refusal is correct — design a graceful path, don't try to jailbreak.
Add the legitimate context up front
I am a security engineer at [company] reviewing our own authentication code before a release. Below is a function we wrote and own. Identify weaknesses in it and explain how an attacker would exploit each one, so we can fix them before we ship. [code]
Fallback patterns
- A clarifying question instead of a dead end.
- A safe alternative ("I can summarize the public info instead").
- For pipelines, route to a human when confidence/eligibility is low.
Guided walkthrough1 of 4
- Inspect the response for a refusal signal before you render it. Never pipe an unchecked response straight into your UI — that is how users get a blank box or a raw object.
- Model refusal or classifier/safety block? A refusal is a judgment about the request; a block is a separate safety layer. Retrying identical input helps with neither, but they point at different fixes.
- Swap the dead end for a clarifying question or a safe alternative, in your own product's voice. The user should get a next step, not an error.
- In a pipeline, route low-confidence or ineligible cases to a human queue instead of guessing or silently dropping them.
Check yourself
0/3- A refusal is an outcome, not an error — detect it before rendering, always.
- Model refusal and classifier block are different things; identify which you got.
- Unwanted refusals usually shrink when you add legitimate context and get specific.
- If a request is genuinely disallowed, refusal is correct — build a graceful path, don't jailbreak.
- Fallbacks in order: clarifying question, safe alternative, human handoff.
Next
- Server-Side Fallbacks & Fallback Credit — the Opus 5 beta that turns a refusal into a normal answer inside one API call, plus the credit token that stops you paying the prompt cache twice on the retry.
- Errors, Rate Limits & Reliability
- Responsible Use, Ethics & Verification
- Troubleshooting: Why Did Claude Do That?