My understanding of Seibel is that Lisp's condition system is designed to avoid exactly the problem of internal details spreading up the stack.
It does so by allowing conditions (of which exceptions are one type) to be handled by a higher level of the call stack without unwinding the call stack, and allows for the determination of which particular condition handler to be made independently (and at a higher level of the call stack) than the implementation of the handler.
The "anti-pattern" may be a result of the way in which other languages implementation of exception (or condition) handling differs from that of Lisp.
> [conditions are] handled by a higher level of the call stack without unwinding the call stack, and allow for the determination of which particular condition handler to be made independently (and at a higher level of the call stack) than the implementation of the handler.
Is exactly what the higher-order function I described would let you do. Why do we need conditions?
Edit: the answer to this question is "because we want to use exceptions". But there's really no need to.
> Is exactly what the higher-order function I described would let you do. Why do we need conditions?
Because conditions let you do that correctly without e.g. changing all intermediate pieces of code so they forward some sort of gigantic mapping of callables through the stack.
A possible benefit of conditions in Common Lisp is more than 25 years worth of implementation experience and full documentation of how the system is structured.
Extensive literature about the language is a defining feature of Lisp.
For those who wonder whether that is worth a new idiom to learn: the stylistic effect is enormous.
For example, there could be 5 layers of code between a condition handler and the code signaling a "file not found" condition, and the top levels of that stack might not even be aware that they could trigger such a condition or even any condition at all.
In some sense, this is the reverse of Java's checked exceptions. There, you have the problem that an interface declares exception X and Y, and an implementation that wants to throw a Z has to encapsulate that exception into a X or an Y. Here, the intermediate layers _can_ be blightfully unaware of those conditions.
A common use case is to use conditions without registered handlers as "break on exception" breakpoints, with the benefit that the human working with the debugger has more options than "stop execution", "continue and pray" and "tweak some memory, set the PC, go, and hope for the best". For example, if the 'open file' system call has a restart, users can easily fix "oops, that lengthy computation is done, but I mistyped that output file name." error conditions.
It does so by allowing conditions (of which exceptions are one type) to be handled by a higher level of the call stack without unwinding the call stack, and allows for the determination of which particular condition handler to be made independently (and at a higher level of the call stack) than the implementation of the handler.
The "anti-pattern" may be a result of the way in which other languages implementation of exception (or condition) handling differs from that of Lisp.