Programmierfehler können in drei Klassen eingeteilt werden.
Syntaxfehler
Schreibfehler in der Codeebene, Befehle sind nicht so formuliert wie sie vom Compiler oder Interpreter erwartet werden. Werden meist beim ersten Lauf des Compilers oder Interpreters erkannt, sind ebenso schnell behoben und somit trivial. Syntaxfehler können theoretisch nur in Interpretern längere Zeit überleben, die keine Syntaxcheck-Funktion über den Gesamtcode haben, wenn sie in einem selten genutzten und nicht getesteten Block liegen.
Semantikfehler
Syntaktisch korrekt, aber Fehler im Codefluss oder in der Codelogik (Umsetzungsebene). Diese können in zwei Unterklassen eingeteilt werden.
In der ersten Unterklasse finden sich z.B. Zuweisungen an die falsche Variable oder Anweisungen in der falschen Reihenfolge, das klassische C-Beispiel des '=' statt '==' Vergleichs, und viele weitere. Streng genommen handelt es sich hier um Syntaxfehler, da der Programmierer etwas anderes hingeschrieben hat als er eigentlich wollte. Da die Anweisungen aber eine korrekte Sprachsyntax aufweisen, können sie vom Compiler oder Interpreter nicht erkannt werden, und machen sich unter Umständen erst sehr viel später und an einer anderen Stelle des Programms bemerkbar, z.B. durch falsche Ergebnisse. Sind deshalb nicht unbedingt leicht zu finden, wenn sie aber entdeckt wurden, sind sie umso schneller behoben.
Die zweite Unterklasse beinhaltet kritische Fehler, wenn das Programm einen illegalen, nicht vorgesehenen Zustand erreicht. Hierunter fallen die meisten LaufzeitFehler. Häufige Ursachen sind:
Werden die möglichen Fehlerzustände abgefangen, z.B. über eine Prüfung, ob eine Speicheranforderung erfolgreich war, oder über eine behandelte Exception für den Fall b=7, dann handelt es sich genau genommen nicht mehr um Fehler in diesem Sinne, da durch die definierte Behandlung kein illegaler Programmzustand mehr erreicht wird.
Design- oder Konzeptfehler
Syntaktisch und semantisch korrekt, aber die Voraussetzungen, Algorithmen und Modelle sind falsch (Fehler in der Algorithmusebene). Sie können auf jeder Ebene und in jeder Größenordnung auftreten. Eine Funktion kann eine mathematische Formel implementieren, von der der Programmierer annimmt, dass sie richtig ist, was aber nicht der Fall ist. Genauso kann aber das Gesamtprogramm eine komplexe Berechnung durchführen, die auf völlig falschen Modellen basiert und ein unsinniges Endergebnis liefert. Die Fehler können aber so subtil sein, dass die falschen Ergebnisse richtig aussehen.
Somit sind dies die gefährlichsten und teuersten Fehler, die ganze Projekte gefährden können. Sie können im frühesten Projektstadium auftreten (Konzeptionierung) und erst im spätesten bemerkt werden (Release), wobei ihre Behebung im schlimmsten Fall ohne eine völlige Neukonzeptionierung und Restrukturierung gar nicht möglich ist.