I usually divide things in "errors" (which are really "invariant violations") and "exceptions". "exceptions", as the name implies, are exceptional, few and when they happen, they're usually my fault, "errors" on the other hand, depending on the user, happens a lot and usually surfaced to the user.

[deleted]

why not divide things into errors and bugs (programming errors)?

That's subtly different. It's secondary whose fault is this, what primarily matters is whether you should continue with the rest of the process.

There is always a cleanup layer, the trick is to choose well between 1 and 2:

  1. Some code in the same OS process is able to bring data back to order.

  2. OS can kill the process and thus kill any corruption that was in its address space.

  3. Hardware on/off button can kill the entire RAM content and thus kill any corruption that spilled over it.
Take for example an unexpected divide by zero, that's a classic invariant violation. The entire process should blow up right there because:

- it knows that the data in memory is currently corrupted,

- it has no code to gently handle the corruption,

- and it knows the worst scenario that can happen: some "graceful stop", etc., routine might decide to save the corrupted data to disk/database/third-party. Unrecoverable panic (uncatchable exception) is a very good generic idea, because persistently-corrupted-data bug is a hundred times worse than any died-with-ugly-message bug as far as users are concerned.

Both bugs and exceptions can be reasonably thought of as programmer error, but they are not the same kind of programmer error. Exceptions are flaws in the code — conditions that could have been caught at compile time with a sufficiently advanced language/compiler. Whereas bugs are conditions that are programatically sound, but violate human expectations.

A little nuance: bugs are not just conditions that are programmatically sound. They can encompass exceptions.

If a bug triggers an exception then with a strong compiler that is sufficiently advanced then these bugs can be found by the compiler.

Bugs require execution so a compiler cannot find bugs.

Exceptions also require execution, but that does not suggest that they are encompassed by bugs. The lack of a third term tells that there is no overlap. If "bug" covered both exceptions and where human expectations are violated, there would necessarily be another term just for the case where human expectations are violated. But there is no such term...

...that I've ever heard. If it is that I've been living under a rock, do tell.

No you haven’t been living under a rock your definitions are just off and you didn’t read carefully what I wrote. Or you’re just overly pedantic.

I wrote bugs can cover exceptions. Think hard about what that sentence means in English. If I can do something it means I can both do something and not do something. So that means there are exceptions that are bugs and exceptions that are not bugs.

The reason why it’s important to illustrate this difference is because a large, large number of exceptions occur as a bug.

> So that means there are exceptions that are bugs

Which, like before, is false. Are you, perhaps, confusing exceptions (the concept; what we're talking about here) with the data structure of the same name? A bug could erroneously lead to the creation of an exception (data structure), but that wouldn't be an exception (concept), that'd just be a bug.

There is no situation where an exception (concept) is also a bug, unless you take "bug" to mean something akin to general "programmer error", where exceptions are subset thereof. But, as before, we know that's not how "bug" is used as there is no other terminology for human expectation violations to fill the void. No need as that is already what "bug" refers to.

> a large, large number of exceptions occur as a bug.

That doesn't really make any sense. Maybe if, again, you have confused exceptions (concept) with exceptions (data structure), then it could start to mean something, but even then "large, large" is one hell of a claim. Let's be real: The vast majority of exceptions (data structure) are created by programmers who mistakenly believe that "exception" is another word for "error". While not exactly a good idea, that use falls under neither exceptions (concept) nor bugs. In second place, exceptions (data structure) are created due to exceptions (concept). I'm sure exceptions (data structure) being created due to bugs has happened before, but I've never seen it.

You’re arguing as though reality cares about your word boundaries. Saying “exceptions are not bugs” because one is a concept and the other is a data structure is like saying a flat tire isn’t a car problem because the air is outside the vehicle. It’s technically true in the same way “rain is just water, not weather” is true. Nobody outside the argument needs a whiteboard to see what’s gone wrong.

An exception is what happens when a bug hits the runtime. The program trips, falls, and throws a message about it. Calling that “not a bug” is like saying your toaster catching fire isn’t a malfunction because combustion is a physical process, not an electrical one. Or saying a sinking ship isn’t in trouble because “leak” is a noun and “disaster” is a category.

In practice, exceptions are how bugs announce their presence. You can keep redrawing the philosophical fence around which one counts as which, but it’s the same as a child insisting the spilled milk isn’t a mess because it’s just “liquid on the table.” Everyone else has already grabbed the paper towels.

> An exception is what happens when a bug hits the runtime.

Remember, "exception" is short for "exceptional event". "An exceptional event is what happens when a bug hits the runtime." means... what, exactly? And let's not forget that you said that not all exceptions are bugs so it seems we also have "An exceptional event is what happens when a bug does not hit the runtime." What is that supposed to mean?

Returning us from la-la land, an exceptional event, or exception, refers to encountering a fundamental flaw in the instruction. Something like divide by zero or accessing an out of bounds index in an array. Things that you would never have reason to carry out and that a more advanced compiler could have reasonably alerted you to before execution.

Bugs are different. They can only be determined under the watchful eye of a human deciding that something isn't behaving correctly. Perhaps your program has a button that is expected to turn on an LED, but instead it launches a nuclear missile. While that is reasonably considered programmer error, that's not a fundamental flaw — that's just not properly capturing the human intent. In another universe that button launching nuclear missiles very well could be the intended behaviour. There is no universe where accessing an out of bounds index is intended.

> exceptions are how bugs announce their presence

Bugs aren't announceable, fundamentally. They can be noticed by a human who understands the intent of the software, but it is impossible for the machine to determine what is and what isn't a bug. The machine can determine what is an exception, though, and that's why exceptions often get special data structures and control flows in programming languages while bugs don't.

You’re still mistaking your own definitions for truth. You’re describing programming as if words create reality, not the other way around. Your claim that bugs “can only be determined by humans” and “machines cannot announce them” is like saying a car cannot have a problem until a mechanic gives it a name. The smoke pouring from the hood does not wait for linguistic permission to exist.

Exceptions are the runtime form of program faults. The fact that we can construct them synthetically or that some are anticipated does not erase their relationship to bugs. You seem to believe that because we can imagine a world where launching a missile is “intended,” it stops being a bug. By that logic, nothing in computing can ever be wrong as long as someone somewhere hypothetically wanted it that way. That isn’t philosophy. It’s a child’s loophole.

Your “fundamental flaw in the instruction” definition collapses immediately under reality. A division by zero is only “fundamental” because of human intent: we chose to define arithmetic that way. Under your logic, if we wrote a compiler that quietly handled it as infinity, exceptions would vanish from the universe. That should tell you that your ontology is not describing truth but just the current convention of language design.

The machine can’t “determine” bugs? Of course it can’t. The machine can’t determine anything. It executes. Yet you just admitted exceptions exist because “the machine determines them.” You’ve built a castle out of circular definitions and are calling it a worldview.

In practice, exceptions are one of the main observable ways that bugs manifest. The rest of us live in the world where programs crash, not in the world where we rename crashes until they sound academic.

> [...] is like saying a car cannot have a problem until a mechanic gives it a name. The smoke pouring from the hood does not wait for linguistic permission to exist.

That doesn't make any sense. But there may be something salvageable in your analogy. Consider the difference between manufacturing defects and wear and tear. You can understand how each, while both able to lead to failure, are different categories of problems?

Good. Now, analogies can only go so far, but we can extrapolate some similarity from that in software. Meaning that both bugs and exceptions are problems, but they are not of the same category. They originate from different conditions. Exceptions are fundamental flaws in the code, while bugs are deviation from human intent.

> Yet you just admitted exceptions exist because “the machine determines them.”

That's right. The machine can determine when an exception occurs. For example, divide by zero. There is no way the machine can carry on once this happens. The machine is capable of addressing such a condition. Which is very different from divide by one when you actually intended to divide by two. This is what differentiates exceptions from bugs and why we have more than one word to describe these things.

> exceptions are one of the main observable ways that bugs manifest.

Maybe you're still confusing the concept with the data structure? Absolutely, a bug can lead to creating an exception (data structure). Consider:

    color sky = "blue";
    if (sky == "blue") { // was intended to be sky != "blue"
        throw "the sky was expected to be blue"; // produces an exception data structure (message, call stack, etc.)
    }
But that wouldn't be an exception (concept), that'd just be a bug. The fault is in the inverted conditional, not a fundamental execution flaw.

The presence of an exception (data structure) does not imply that there is an exception (concept). The overlapping use of words is a bit unfortunate, perhaps — albeit consistent with error (concept) and error (data structure), but the difference between a data structure and a concept should not confuse anyone.

Exceptions (concept), on the other hand, looks more like:

    object.methodThatDoesNotExist();
The code is fundamentally flawed. The machine is, in this case, quite able to determine that you screwed up. If you have a sufficiently advanced compiler, you'd be warned at compile time that methodThatDoesNotExist cannot be called. But if that condition evades the compiler then it would lead to an exceptional event at run time instead.

First, your categories are not universal. They depend on the language and the runtime. 1. Divide by zero In IEEE floating point you can define it to yield Infinity or NaN and keep going. In some languages it raises an exception. In C with integers you get undefined behavior with no exception at all. If your claim were about a fundamental flaw of code itself, the result would not change across environments. It does. So your category is a policy choice, not a law of nature. 2. Out of bounds In Java you get an IndexOutOfBoundsException. In C you can trample memory and never raise anything. Same code pattern, different outcome. Again this shows your supposed bright line is just a design decision. 3. methodThatDoesNotExist In a statically typed language this is a compile time error and never throws at runtime. In a dynamic language it can throw NoSuchMethod at runtime. Same text, different category, based on tooling. That is not a fundamental metaphysics of exceptions. It is the compiler and runtime drawing the line.

Conclusion from 1 through 3 Your definition of exception as a fundamental flaw collapses the moment we cross a language boundary. What you are calling fundamental is actually configurable convention.

Second, your machine versus human distinction is self defeating.

You say the machine can determine exceptions but only humans can determine bugs. The machine does not determine anything. It executes rules we wrote. If a rule maps a state to raise an exception, the machine raises one. Whether that state is a bug is defined by the spec. If the spec says division by zero must never occur in production, any runtime that hits it is a bug. If the spec says handle it as Infinity, then hitting it is not a bug. The label follows intent and contract, not the instruction pointer.

Obvious example A payment service has a rule that user input must be validated before division. A request slips through with divisor zero and the service throws. That is a bug even if the language designer felt very proud of raising an ArithmeticException. Flip the rule. If the service is specified to accept zero and return a sentinel value, then raising an exception is itself the bug.

Third, the data structure versus concept move does not rescue the argument.

Yes, we all know you can throw an object on purpose. Yes, we all know many libraries create rich exception objects. None of that changes the core point. In a nontrivial system, unhandled exceptions or exceptions raised in states that the spec forbids are bugs by definition. The exception is the transport. The bug is the violation that made the transport fire.

Your own toy example proves it You show an inverted conditional that throws. You say that is not an exception in the conceptual sense. But the system would still page the on call, still fail the request, still violate the acceptance test. Every operator and every customer would call that a bug. You are trying to win by relabeling the alarm as not part of the fire drill.

Fourth, here are obvious scenarios that make the logic clear to anyone.

Elevator Spec: doors must never open between floors. Code hits that state and trips a safety exception. If that ever happens in production, it is a bug. If the safety system decides to log and keep moving instead, and the spec requires a stop, then not throwing is the bug. The exception path is just the messenger.

Bank transfers Spec: never double charge. Off by one posts the same transfer twice. The code throws on the second insert due to a unique constraint. If it throws, the incident is a bug. If it does not throw because the database had no constraint and you silently post two charges, that outcome is a bug. In both cases the presence or absence of an exception is not the category. The spec is the category. The bug is the deviation.

Medical device Spec: sensor readings out of range must be clamped and logged, not crash the loop. If the runtime raises an exception and the loop dies, that exception is the manifestation of a bug. If the runtime never raises and you keep using garbage without logging, that silent path is the bug. Same state space. Different handling. The spec decides which path is the failure.

Toaster Spec: pop after two minutes. The timer arithmetic overflows and you get a runtime exception in the control loop. That exception is how the bug announced itself. In a different implementation the overflow wraps and the toaster never pops. No exception at all. Still a bug.

These are obvious because everyone can see that what matters is the contract. The exception is only a vehicle for discovery.

Fifth, the correct taxonomy already exists and it does not match your story.

Industry standards separate three things. A fault is the cause in the code or design. An error is the incorrect internal state. A failure is the externally visible deviation. Exceptions are one mechanism for surfacing an error or failure. When an exception causes a failure relative to the spec, we have a bug. When an exception is expected and fully handled within the spec, we do not. This mapping is stable across languages in a way your concept versus data structure split is not.

Final point

Your thesis needs both of these to be true at once.

A) Exceptions mark fundamental flaws independent of intent. B) Bugs are only deviations from intent.

But we have shown counterexamples where intent flips the classification and where language choice flips the behavior. That means A and B cannot both stand. Once A falls, your whole distinction reduces to wordplay. Once B stands, the only consistent rule is this:

If an exception leads the program to violate its requirements, it is evidence of a bug. If it does not, it is routine control flow. In practice many exceptions are how bugs announce themselves. That is why production teams triage exception rates and not treatises on metaphysics.

> What you are calling fundamental is actually configurable convention.

Not within the topic's layer of abstraction. I can see you put a lot of thought into this, and if you were writing in a vacuum it might even be interesting, but discussion relies on context...

> If that ever happens in production, it is a bug.

Right. A bug, not an exception. Overloading the use of exception data structures and associated control flows does not imply that there is an exception in concept, just like using an error data structure to represent an email address[1] does not imply that you are dealing with an error in concept. It's just an email address.

> If it throws, the incident is a bug.

Right. A bug, not an exception. Again, just because you overloaded the use of a feature intended for dealing with exceptions for other purposes does not mean that you have an exception in concept. Just as an email address does not become a conceptual error just because you put it in an error data structure[1].

> If the runtime raises an exception and the loop dies, that exception is the manifestation of a bug.

Right. A bug, not an exception. I sense a recurring theme here. It is clear now that you've undeniably confused exceptions (data structure) with exceptions (concept). You obviously missed a lot of context so this may come as a surprise, but we were talking about the concept of programmer error. Data structures used in an implementation find no relevance here.

> In practice many exceptions are how bugs announce themselves.

As bugs and exceptions are different categories within the broader concept of programmer error, you could equally say "In practice many bugs are how bugs announce themselves". How, exactly, am I to grok that? I honestly have no idea what to make of that statement.

[1] let email = Error("foo@example.com")

>Not within the topic’s layer of abstraction. I can see you put a lot of thought into this, and if you were writing in a vacuum it might even be interesting, but discussion relies on context…

You keep invoking “context” as a shield for avoiding substance. Context doesn’t change semantics. Arithmetic faults, null dereferences, and contract violations are not “configurable conventions” no matter how much pseudo-philosophical varnish you apply. Calling fundamental runtime behavior a “configurable convention” is like claiming gravity is optional if you talk about it at the right “layer of abstraction.” It sounds deep until anyone with an actual engineering background reads it.

>Right. A bug, not an exception. Overloading the use of exception data structures and associated control flows does not imply that there is an exception in concept, just like using an error data structure to represent an email address[1] does not imply that you are dealing with an error in concept. It’s just an email address.

Your “email analogy” is nonsense. The fact that something can be misused doesn’t invalidate its conceptual role. By that logic, if someone writes int banana = "hello", integers stop existing. Exceptions are not defined by their container type. They are defined by the runtime condition they represent. The fact that you have to keep insisting otherwise shows you have no grasp of the operational meaning of exceptions beyond the syntax of throw.

>Right. A bug, not an exception. Again, just because you overloaded the use of a feature intended for dealing with exceptions for other purposes does not mean that you have an exception in concept. Just as an email address does not become a conceptual error just because you put it in an error data structure[1].

Repeating the same broken analogy doesn’t make it coherent. You keep hammering at this contrived misuse like it proves anything. It doesn’t. It’s a straw man. Nobody is arguing that misusing the mechanism redefines the concept. You’ve constructed a toy example where you intentionally misuse a type and then triumphantly point to your own confusion as evidence. This is the intellectual equivalent of setting your keyboard on fire and declaring that typing is impossible.

>Right. A bug, not an exception. I sense a recurring theme here. It is clear now that you’ve undeniably confused exceptions (data structure) with exceptions (concept). You obviously missed a lot of context so this may come as a surprise, but we were talking about the concept of programmer error. Data structures used in an implementation find no relevance here.

You’re projecting your own confusion. You can’t even decide which layer you’re talking about. One moment you say exceptions are “data structures,” the next you say the data structure is irrelevant. You wave your hands at “concepts” but those concepts are precisely instantiated through those data structures. You don’t get to discard the implementation layer when it undermines your argument. Pretending the runtime’s behavior is irrelevant to the “concept of programmer error” is a convenient way to avoid admitting that bugs and exceptions are related manifestations of the same fault system. You’re not clarifying categories; you’re just renaming them until they stop overlapping.

>As bugs and exceptions are different categories within the broader concept of programmer error, you could equally say “In practice many bugs are how bugs announce themselves”. How, exactly, am I to grok that? I honestly have no idea what to make of that statement.

Of course you don’t. The problem isn’t the statement; it’s your refusal to recognize that categories can overlap without collapsing. Saying exceptions often announce bugs is perfectly coherent: bugs are latent causes, exceptions are how those causes surface at runtime. Your confusion stems from trying to turn mutually informative categories into mutually exclusive ones. It’s the same error a freshman makes when they insist that “rain isn’t weather because weather causes rain.”

[1] The Error("foo@example.com") example doesn’t reveal deep insight; it reveals that you can misuse syntax. That’s not philosophy, it’s just bad code.

> They are defined by the runtime condition they represent.

Exactly. Exceptions represent conditions that violate the rules of the computing environment, while bugs represent conditions that violate "business" rules.

> Saying exceptions often announce bugs is perfectly coherent

Not really. If it were coherent we wouldn't be here. But perhaps what you are grasping to say is that it is possible that a bug could "corrupt" the computing environment, which could then also lead to an exception later on?

Allowing user input of "0" where the business rules say that "0" input is invalid would be considered a bug, and later when that 0 input is used as a divisor would see an exception (in an environment where divide by 0 is not permitted, for those who struggle). The exception in this case would likely reveal that there is also a bug in the user input.

But that does not imply that exceptions encompass bugs. Those are independent events, both wanting their own independent resolutions.

> But that does not imply that exceptions encompass bugs. Those are independent events, both wanting their own independent resolutions.

they do, unless you use exceptions for control flow

Neither exceptions, the concept, nor exceptions, the data structure, have anything to do with control flow. You could be thinking of exception handlers, which refers to a control flow mechanism, but if you were you'd be going completely off the rails.

[deleted]

I'm currently working on something that requires a GPU with CUDA at runtime. If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely. If the user somehow ended up sending data to the GPU that isn't compatible/couldn't be converted or whatever, then that'd be an user error, they could probably fix that themselves.

But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional, and requires us to stop and not continue.

> If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely.

That depends if it is due to the programmer making a mistake in the code or an environmental condition (e.g. failing hardware). The former is exceptional if detected, a bug if not detected (i.e. the program errantly carries on as if nothing happened, much the dismay of the user), while the latter is a regular error.

> But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional

Not having a GPU isn't exceptional in any sense of the word. It is very much an expected condition. Normally the programmer will probe the system to detect if there is one and if there isn't, fall back to some other option (e.g. CPU processing or, at very least, gracefully exiting with feedback on how to resolve).

The programmer failing to do that is exceptional, though. Exceptions are "runtime compiler errors". A theoretical compiler could detect that you forgot to check for the presence of a GPU before your program is ever run.

The grey area is malfunctioning CPU/memory. That isn't programmer error, but we also don't have a good way to think about it as a regular error either. This is what "bug" was originally intended to refer to, but that usage moved on long ago and there is seemingly no replacement.

[deleted]

That’s interesting. I’d actually consider this a user error because it’s only in the user’s power to fix it.

For example:

1. You’d want to display a message that they need a GPU.

2. Call stack information isn’t helpful in diagnosing the issue.

[deleted]

Not all exceptional circumstances are bugs