Map

Error-stack discard anti-pattern

Wiki conceptsoftware-qualitysecurityc โ†ณ show in map Markdown
title
Error-stack discard anti-pattern
type
concept
summary
Suppressing one inconvenient error by clearing a library's entire shared error channel, silently discarding unrelated errors that belong to other code
tags
software-quality, security, c
created
2026-07-21
updated
2026-07-21

An error-handling anti-pattern where code makes an inconvenient error "go away" by clearing a library's shared, stateful error channel wholesale โ€” discarding not just the one error it cared about but every other error on the channel, including ones left by unrelated code that may signal real problems. Named from Julian Andres Klode's OpenSSL writeup (openssl-error-handling-pandemic), where the channel is OpenSSL's error stack and the clearing call is ERR_clear_error().

The shape

The precondition is a library that accumulates errors in shared process/thread state rather than returning them inline โ€” OpenSSL's error stack is the archetype. Two forms:

  • Blanket pre-clear: wipe the whole channel before your operation so leftover errors don't trip your happy path. You've now discarded whatever earlier code left there.
  • Check-top-then-discard: read the most recent error, decide it's tolerable, and clear everything. Errors below the top vanish silently.

Both turn "an error occurred somewhere" into "no error." In security-sensitive code that's the worst possible transformation, because the whole point of the error channel is to refuse to proceed on an unhandled failure.

Why it spreads

It looks locally correct and it makes the immediate symptom disappear, so it passes review and gets copied โ€” even into upstream guidance. The deeper cause is a mental model mismatch: authors treat the channel as a single error slot when it's actually a stack, so "clear the error" reads as "clear my error" when it means "clear everyone's errors." This is a recurring failure at library boundaries with implicit, shared error state.

The correct pattern

Scope your own error context instead of clearing globally. OpenSSL's answer is ERR_set_mark() / ERR_pop_to_mark(): push a mark, run your operations, pop back to the mark โ€” removing only the errors you produced and leaving unrelated ones intact. The general principle: never discard an error channel you don't own the entirety of; fix or handle the specific error at its source, and if you must suppress, suppress precisely (by mark, by code) rather than by nuking the channel.

Related: openssl-error-handling-pandemic (the source case), and the review-can't-catch-this theme in reviewing-ai-code / testing-heavy-no-review-workflow โ€” this is exactly the kind of subtle correctness bug that slips past human review and wants randomized/differential testing instead.