A taxonomy of bugs - Lispl-Wicht/c-logo-s GitHub Wiki
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:
Everything becomes a bug:
- syntax error
- logic error
- lag
- performance issue
- network latency
- user misunderstanding
- exploit / hack (!)
This destroys explanatory power.
“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.
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.
- Thomas Edison (1870s) used bug to mean a technical defect or glitch.
- Early radio engineers used bug for intermittent faults.
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.
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)
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.
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.
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.
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."
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.
reader-errorprogram-errorcompile-time error-
simple-error(sometimes)
Example:
(cons 'a)
;; invalid number of arguments: 1Engineering stance: fix before thinking further
Pedagogical stance: Rule learning, grammar, surface structure
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-errordivision-by-zerounbound-variablefile-errorcell-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."
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:
tracestepinspection- REPL experimentation
Pedagogical stance: The learner, not the machine, must notice the mismatch.
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.
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:
warningstyle-warningcustom non-error conditions
Example:
(defmethod foo ((x t)) ...)
;; style-warning: method specialisation too generalThese 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 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 |