
When the check that was supposed to stop an action errors, times out, or comes back empty, and the product allows the action, stop that path tonight. The next error must be a denial. Keep the error. Do not send the model back in to decide whether the action was fine. Count how many actions passed while an error was being treated as a yes. If you cannot point at the branch where a failure becomes permission, you do not have a guard. You have a function that usually returns, and a default you have not read.
This is the error path. It is not the decision to turn a live feature off because the next answer can hurt someone, and it is not the decision to leave a feature on behind a person who can reject a wrong answer. Those assume the check returned a decision. Here the check did not return a decision, and the product continued. It is also not the afternoon an agent has already written a wrong row and you are reversing it. Reversal is what you do for the action that got through. Tonight's change is so the next exception does not get through. A duplicate retry is a different defect: the action was intended, and it landed twice. A guard that fails open will happily approve both.
None of what follows is a finding that your classifier is unsafe, and none of it is legal advice. A model that returns "allow" on a bad input is a wrong decision. An exception that you treat as allow is a missing decision. They look the same in the customer's inbox. They are repaired in different places. Do not spend the night tuning a prompt to fix a catch block.
Failing open is a design, not a bad day. CWE-636, "Not Failing Securely ('Failing Open')," is the weakness where "the product encounters an error condition or failure" and "its design requires it to fall back to a state that is less secure than other options that are available, such as selecting the weakest encryption algorithm or using the most permissive access control restrictions." The extended description names the motive: the weakness "typically occurs as a result of wanting to 'fail functional' to minimize administration and support costs, instead of 'failing safe.'" The consequence listed is a bypass of access control, "often contradictory to what the product's administrator expects" (MITRE, CWE-636, CWE 4.20). A guardrail call that throws, times out, or returns an empty body, followed by code that proceeds with the refund, the email, or the write, is that fallback. The administrator expected a check. The design delivered a green light whenever the check could not speak. The entry is a class of weakness, not a CVE against your repository, and the research note on the page says design issues of this kind are rarely what shows up in public vulnerability lists. Absence from a CVE feed is not evidence you fail closed.
The category that contains this weakness is wider than the weakness, and the rates are the category's. OWASP Top 10:2025 A10, Mishandling of Exceptional Conditions, is new in that edition. The background says the category "contains 24 CWEs and focuses on improper error handling, logical errors, failing open, and other related scenarios," and it names CWE-636 among the notable entries, beside sensitive error messages, missing parameters, insufficient privileges, and null dereference. The score table on the same page prints maximum incidence 20.67%, average incidence 2.95%, maximum coverage 100.00%, average coverage 37.95%, 769,581 occurrences, and 3,416 CVEs. Maximum is not the average. Coverage is not incidence. 769,581 is occurrences in the contributed testing data, not a count of AI guards, and not a count of your exceptions. 20.67% is the maximum incidence rate of this whole category. It is not the rate at which fail-open occurs, and it is not a rate for a language-model check. The prevention text is the line to steal, and it is narrower than the table: "If you are part way through a transaction of any kind, it is extremely important that you roll back every part of the transaction and start again (also known as failing closed). Attempting to recover a transaction part way through is often where we create unrecoverable mistakes" (OWASP, A10:2025 Mishandling of Exceptional Conditions). Failing closed, in that sentence, means the transaction does not complete. It does not mean you show the user a stack trace. It does not mean you retry the model until something returns.
A guard that answers wrong is a different measurement, and it does not license an exception to mean yes. Bassani and Sanchez evaluated 15 guardrail models against mutations and against attacks, and reported false-negative rates on unsafe prompts. The abstract's example is precise: "a single adversarial token can deceive them 44.5% of the time on average" (Bassani and Sanchez, On Guardrail Models' Robustness to Mutations and Adversarial Attacks, Findings of EMNLP 2025, pages 16995–17006). That 44.5% is the mean, across the fifteen models, of the false-negative rate when one adversarial suffix token is attached. It is not one product's rate. The table's cells for that row are not the same number: the prose gives Llama Guard 3 8B at 54 out of 100 very unsafe prompts with a single token, and the same paragraph says four suffix tokens can reliably evade all of the models they tested. A mean hides a model that barely moves and a model that almost always misses. The limitations section is part of the result. The unsafe set is 100 prompts, English only, models mostly up to about ten billion parameters, and the authors did not test closed commercial moderation APIs. "Evading guardrail models does not necessarily lead to obtaining unsafe information from the LLMs they protect." The evaluation "only has negative predictive power": doing well on these prompts does not promise the same on more deceptive ones. Read 44.5% as a laboratory average on a constructed suffix, not as the share of your users who are attacking you, and not as the repair for a timeout. A classifier that says allow, wrongly, is a model problem. A timeout you treat as allow is a few lines of code. Fix the lines tonight. Schedule the model problem for a set you can rerun.
Find the branch. Search for the call that is supposed to stop the action: the classifier, the allow-list, the policy service, the human-approval check. Read what happens when that call throws, when it exceeds the deadline, when the body is empty, and when the status is not the one you documented. Four shapes cover the incidents that actually ship. The exception is swallowed and the action runs. The timeout is caught and the action runs, because hanging felt worse than sending. An empty verdict is treated as the default, and the default is allow. A failed approval service is read as "no reviewer objected." Any one of the four is fail-open. A comment that says "fail open for availability" is the CWE's motive written into the diff. Availability of a refund, a send, or a write is not the availability you were protecting.
Make the next error a denial. The action does not run. The user sees a refusal or a queue, in words, not a success. The error is stored: which check, what it returned or that it returned nothing, the time, and the action that did not happen. OWASP's line about rolling back a half-finished transaction applies if you have already taken the first step — a hold on a card, a draft that is about to send. Undo that step. Do not leave a half-write because the second call failed and you wanted the first call to "count." Do not retry the check in a loop against the same model and then allow on the third empty body. A retry that changes an error into an allow is the same bug with a delay. When the agent already wrote the row is the repair for the row that got through before you found the branch. Do not ask that article's model to clean up this article's exception.
Count the window, then stop counting and start denying. You need one number: how many actions completed while the check was not a decision. That number is an incident fact. It is not a benchmark, and it is not the 2.95% average incidence of an OWASP category. If you cannot count, because a failure was not logged, the first denial is still correct, and the missing count is a second defect. Write down that the count does not exist. A team that waits for a perfect log before it changes the default will spend the night with the default. The decision to take a feature offline entirely, because the next answer can hurt and nobody awake can stop it, is when to turn a live AI feature off. Use it if the denial you just installed is not actually a denial — if some other path still performs the action with no check at all. Use the smaller fix when the only hole is the error path.
Do not confuse a person in the loop with a check that failed. Leaving a feature on behind a reviewer assumes the reviewer sees the action before it lands, and that they have rejected a wrong answer they already knew was wrong. An exception that skips the reviewer never gives them that chance. Their drill is real and it is a different article: when to leave a wrong AI feature on. Citing the drill as proof you fail closed is how the catch block survives review. The reviewer cannot reject what the code already did. If the approval service itself is down, "no objection" is the empty verdict. Treat the outage as a denial of the action, not as a vacant signature.
The shape that makes the denial obvious is a product with more than one action, and a guard in front of the ones that change something. An AI support agent for a DTC ecommerce brand answers from order data and policies, and puts lookups, returns, and address changes behind permission guardrails, with escalation to a person when confidence is low. Nothing in that description is a headcount, a duration, or a result figure, and it is not a claim about an outage. The shape is the test: if the guardrail call fails, the return does not initiate, and the lookup can keep answering. A design that uses one boolean for "the model may do anything," and sets that boolean true in the catch, cannot make that split. It can only be on or off.
There is a version of this night where hiring a production engagement is the wrong purchase. The error has not happened, and you are designing the call for the first time. Fail closed in the design, and you do not need a rescue to type an else. Nothing is in production. The failure in front of you is a wrong sentence with no action behind it — a bad draft a person will read. That is a quality problem, and a denial of a write you do not perform is theatre. A customer has already seen another customer's data. The first hour is the tenant boundary, not a guardrail default. Or no metric was ever named, so you cannot say what the action was supposed to move, and a tighter catch will not invent the metric.
Where the feature is already live, the error path allows an action, and you can point at the branch, the work is the denial, the log, and the count, then the evaluation of whatever the guard was supposed to decide. That sequence is what an AI pilot failed to reach production engagement owes you when the pilot's guard was a comment: an audit in weeks one and two, then the path that cannot act without a decision, measured against a number you agreed. If the agreed metric does not move, you do not pay for the build. The findings of a two-week AI readiness assessment are yours whether or not that build happens. AI evaluation and observability is how you learn, afterwards, whether the guard's actual decisions are any good — the question Bassani and Sanchez measured, which you do not answer by changing a catch.
On the night the log shows an exception and then a successful action, change the default before you change the model. The next error denies. The error is kept. The count of what already passed is written down, or the absence of the count is written down. The model is not invited to bless the exception. A guard that only works when it works is not a guard. It is a suggestion, and a suggestion is what the action had already ignored.
Related: AI pilot failed to reach production
Find this useful? Tell Google to show you more of it.
