A taxonomy of bugs - Lispl-Wicht/c-logo-s GitHub Wiki

Current situation of the term "bug" (4 July 2026)

The meaning of "bug" is perfectly blurred today: Particularly less-informed "gaming influencer" assume a graphical application as "bugging" if the animated graphics are lagging. And this assumption may even lead to the conclusion, if something "bugs" it is most likely "hacked".

So there are two degradations of the term observable:

A. Semantic flattening

Everything becomes a bug:

  • syntax error
  • logic error
  • lag
  • performance issue
  • network latency
  • user misunderstanding
  • exploit / hack (!)

This destroys explanatory power.


B. Agency confusion (especially in gaming discourse)

“something bugs” → “it is hacked”

This collapses:

  • accident
  • design
  • limitation
  • malice

For education, this is extremely problematic, because it removes responsibility and understanding.

Agency confusion externalises blame and suppresses learning. Therefore, here the goal is not to police language, but to restore distinctions that make thinking possible.


Historical background

A frequently quoted humorous note of an incident of finding a moth in a Mark II in 1947 ("first actual case of bug being found") indicates that the term is older:

"actual bug" only makes sense if bug was already metaphorical.

The term already meant:

something small, elusive, hard to reproduce, and annoying

The metaphor was:

  • bugs are hard to see
  • they leave indirect traces
  • they may disappear when observed

This metaphor maps perfectly to logic errors and emergent behaviour — not just hardware faults.

So historically, "bug" was always blurred, even before software existed.


Three dominant terminological traditions

1. Engineering / Systems tradition

A bug is:

a deviation from the specification

Here:

  • unexpected behaviour = bug only if it violates a formal or informal spec
  • if behaviour is "surprising but correct", it’s not a bug

This tradition dominates:

  • compilers
  • operating systems
  • standards-driven languages (C, Java, Common Lisp spec)

2. Programming practice tradition

A bug is:

something that makes the program not do what the programmer intended

Here:

  • intention matters
  • "it runs but does the wrong thing" is definitely a bug
  • this includes logic errors, algorithmic mistakes, wrong assumptions

This is the tradition most programmers might actually operate in.


3. Constructionist / Papert tradition (→ mathematics education)

A bug is:

a productive misunderstanding revealed by execution

Papert’s key move was reframing:

  • bugs are not failures
  • they are artefacts of thinking
  • they are opportunities to inspect one’s mental model

In Mindstorms (see pp. 22-23, 60-62, 79-93), a bug is neither moral nor technical -- it is epistemic.

Note: Papert did not introduce the idea that errors can be epistemically meaningful. Rather, he integrated existing traditions from mathematics education and cognitive development into a computational setting, where debugging becomes a direct interaction with the learner’s model of the world.


Why a clear taxonomy is crucial in the Computational Thinking (CT) discourse

CT is often used as a curricular shorthand for an “analytical approach” to problem solving, drawing on work such as Brennan and Resnick’s framework, which emphasises practices like testing and debugging (Sun et. al. 2024; Brennan & Resnick 2012).

For both analytical work and curriculum design, however, a precise notion of what counts as a bug is essential. Without it, the core skill of debugging cannot be cleanly defined, taught, or assessed.

The difficulty is that the term “bug” is highly overloaded.

"Unexpected behaviour" is not a single phenomenon.

In practice, calling everything a bug collapses important distinctions between:

  • syntax
  • semantics
  • intention
  • expectation
  • environment
  • pedagogy

This collapse is often harmless for experienced practitioners, but it becomes a serious obstacle in learning contexts, where these distinctions are exactly what needs to be acquired.


A useful taxonomy therefore should be historically grounded, but more importantly it should recover and operationalise distinctions that are otherwise lost in everyday usage.


Level-n bug taxonomy

Level-0: Non-bugs

Not bugs at all.

  • intended behaviour
  • system limitation
  • performance artefacts
  • external constraints

Common Lisp alignment:

  • No condition at all
  • Or possibly style-warning (optional, advisory)

Pedagogical stance: explain, don’t debug or: "This is how the system works."


Level-1 bugs: Formal bugs

Violations detectable without running the program

Includes:

  • syntax errors
  • arity mismatches
  • static semantic violations

These are:

  • machine-recognisable
  • spec-defined
  • detected before or at invocation

Level-1 bugs are non-negotiable violations of form.

Common Lisp manifestations:

  • reader-error
  • program-error
  • compile-time error
  • simple-error (sometimes)

Example:

(cons 'a)
;; invalid number of arguments: 1

Engineering stance: fix before thinking further

Pedagogical stance: Rule learning, grammar, surface structure


Level-2 bugs: Runtime bugs

Failures during execution

Includes:

  • division by zero
  • wrong type at runtime
  • unhandled conditions

Level-2 bugs are violations of execution.

Canonical Common Lisp conditions:

  • type-error
  • division-by-zero
  • unbound-variable
  • file-error
  • cell-error

Key point: These are recoverable by design.

The debugger offers restarts, not just a stack trace.

Engineering stance: handle or redesign

Pedagogical stance: "Your model of execution was incomplete."


Level-3 bugs: Epistemic bugs ("Papert's bugs")

The program is correct, but the mental model is not.

Properties:

  • no error messages
  • no exceptions
  • behaviour is surprising
  • reveals a misconception

Nothing is wrong in a narrower sense but something is learned.

This is where:

  • debugging = thinking
  • running the program = probing the ideas

The most important bugs are the ones the computer cannot detect.

In Common Lisp:

  • these bugs manifest as values
  • intentionally no conditions
    • the system cannot know the programmer’s intent
    • the semantics are correct
    • raising a condition would be lying
  • debugging uses:
    • trace
    • step
    • inspection
    • REPL experimentation

Pedagogical stance: The learner, not the machine, must notice the mismatch.


Side note: Level-3 Bug vs. Kludge (/kluːdʒ/) -- orthogonal concepts

A word that circulated orally in U.S. engineering and electronics slang during the 1940s-50s before written down:

A kludge is an awkward, improvised, inelegant but effective solution.

A kludge feels:

  • clever and
  • clumsy

So maybe it stems from Yiddish/German roots: klug = clever / klotz = clump

A kludge is a solution that functions correctly but whose structure is driven by contingency rather than understanding. It is therefore not a language failure, but a design choice under pressure. (For a slightly different interpretation see Harvey 1997, p. 29).

Important distinctions:

  • Bugs can be fixed without changing design
  • Kludges are design debt
  • Removing a kludge often requires re-thinking, not patching

A system may be:

  • buggy but elegant
  • correct but kludged
  • both
  • neither

Kludges often originate when:

  • Level-3 bugs are silenced rather than resolved
  • constraints force premature commitment
  • local fixes accumulate without revisiting representation

In Papert’s sense, a kludge reflects unrepaired thinking, not merely incorrect thinking.


Level-4 bugs: Pragmatic / interaction bugs

Mismatch between user expectation and system design

Includes:

  • evaluation order surprises
  • precedence misunderstandings
  • scope confusions
  • interaction design flaws

These are often:

  • not fixable by "correct code"
  • solvable by better explanation or tooling

Common Lisp alignment:

Often surfaced as:

Example:

(defmethod foo ((x t)) ...)
;; style-warning: method specialisation too general

These are:

  • not wrong
  • but suspicious
  • socially negotiated between programmer and system

Pedagogical stance: meta-reflection or: "This works -- but are you sure this is what you mean?”


Logo's error processing

Logo's error processing is designed to recast many Level-1 and Level-2 situations into Level-3 learning opportunities. This is because Logo’s error system is asymmetric by design:

System Default response to error
Common Lisp Invoke debugger, expose control
Logo Explain intention mismatch, resume dialogue

Thus:

  • Some errors that would be Level-2 in CL are presented as Level-3 in Logo.
  • Warnings are linguistically softened into suggestions (“Assuming you meant…”).

This is not a weakness -- it is didactic intent.

Berkeley Logo's canonical list of Logo error messages demonstrates this:

Reference manual, pp. 93-94 plus Level-n bug column (dicussable):

Code Message Level-n bug
0 Fatal internal error (can't be caught) Level-0 / system
1 Out of memory Level-2
2 Stack overflow Level-2
3 Turtle out of bounds Level-3
4 <proc> doesn’t like datum as input (not recoverable) Level-2
5 <proc> didn’t output to <proc> Level-3
6 Not enough inputs to <proc> Level-1
7 <proc> doesn’t like datum as input (recoverable) Level-2
8 Too much inside ()’s Level-1
9 You don’t say what to do with <datum> Level-3
10 ')' not found Level-1
11 <var> has no value Level-3
12 Unexpected ')' Level-1
13 I don’t know how to <proc> (recoverable) Level-3
14 Can’t find catch tag for <throwtag> Level-2
15 <proc> is already defined Level-4
16 Stopped Level-4
17 Already dribbling Level-4
18 File system error Level-0 / system
19 Assuming you mean IFELSE, not IF (warning only) Level-4
20 <var> shadowed by local in procedure call (warning only) Level-4
21 Throw "Error Level-3 (intentional)
22 <proc> is a primitive Level-4
23 Can’t use TO inside a procedure Level-1 / Level-4
24 I don’t know how to <proc> (not recoverable) Level-2
25 IFTRUE/IFFALSE without TEST Level-3
26 Unexpected ']' Level-1
27 Unexpected '}' Level-1
28 Couldn’t initialize graphics Level-0 / system
29 Macro returned value instead of a list Level-2 / Level-3
30 You don’t say what to do with <value> Level-3
31 Can only use STOP or OUTPUT inside a procedure Level-1
32 APPLY doesn’t like <badthing> as input Level-2
33 END inside multi-line instruction Level-1
34 Really out of memory (can’t be caught) Level-0 / system
35 user-generated error message (THROW "ERROR message) Level-3 (explicit)
36 END inside multi-line instruction Level-1
37 Bad default expression for optional input: <expr> Level-4
38 Can’t use OUTPUT or STOP inside RUNRESULT Level-1
39 Assuming you meant ’FD 100’, not FD100 (or similar) Level-4
40 I can’t open file <filename> Level-2
41 File <filename> already open Level-4
42 File <filename> not open Level-2
43 Runlist [<expr> <expr>] has more than one expression. Level-1
⚠️ **GitHub.com Fallback** ⚠️