Suchen

Leitfaden · Programmierung & Entwicklung

Debugging für Einsteiger: Fehler im Code systematisch finden

Beim Debugging suchst du nicht irgendwo nach dem Fehler, sondern gehst in festen Schritten vor: Problem beschreiben, zuverlässig auslösen, Fehlermeldung lesen, Ursache eingrenzen, gezielt ändern und erneut prüfen.

Nahaufnahme eines Bildschirms mit vielen Zeilen Quelltext

Das Wichtigste in Kürze

  • Syntaxfehler verhindern den Start, Laufzeitfehler brechen die Ausführung ab, Logikfehler liefern ohne Meldung ein falsches Ergebnis.
  • Ein Python-Traceback endet mit dem eigentlichen Fehler, ein Node.js-Stacktrace beginnt damit; in beiden Fällen ist die genannte Zeile ein Startpunkt, nicht unbedingt die Ursache.
  • Ändere immer nur eine Sache und führe den Ablauf danach mit derselben Eingabe erneut aus.
  • Ein minimales Beispiel und das Halbieren des Suchraums, im Git-Verlauf mit git bisect, grenzen Fehler schneller ein als Raten.

Was Debugging bedeutet

Debugging ist das systematische Finden und Beheben von Fehlern in einem Programm. Ein Fehler kann dazu führen, dass der Code gar nicht startet, mitten in der Ausführung abbricht oder ein Ergebnis liefert, das formal gültig, aber inhaltlich falsch ist.

Der Unterschied ist wichtig: Eine Fehlermeldung zeigt oft direkt auf eine Stelle. Bei einem falschen Ergebnis kann die Ursache dagegen weit vor der Stelle liegen, an der du es bemerkst, etwa bei einer Eingabe, einer Berechnung oder einer Bedingung.

Zuerst das Problem beschreiben und auslösen

Bevor du etwas änderst, schreibe auf, was passiert und was du erwartet hast. „Der Code funktioniert nicht" ist zu ungenau. Hilfreich ist: „Bei einer leeren Liste bricht das Programm ab" oder „Für diese Eingabe kommt 2.0 heraus statt 4.0".

Dann sorgst du dafür, dass du den Fehler zuverlässig auslösen kannst: dieselbe Eingabe, dieselben Schritte, derselbe Startzustand. Verändere dabei nicht mehrere Dinge gleichzeitig, sonst weißt du nicht, was gewirkt hat. Tritt der Fehler nur manchmal auf, suche nach Unterschieden zwischen den Läufen: Reihenfolge der Aktionen, fehlende Werte, Zustand beim Start.

Drei Fehlerarten unterscheiden

Syntaxfehler

Der Code entspricht nicht den Regeln der Sprache, das Programm startet gar nicht erst. In diesem Beispiel fehlt nach der Bedingung der Doppelpunkt:

Python
werte = [2, 4, 6]
if len(werte) > 0
    print("Liste hat Werte")
Text
  File "pruefen.py", line 2
    if len(werte) > 0
                     ^
SyntaxError: expected ':'

Python zeigt die Zeile und markiert die Stelle, an der der Fehler erkannt wurde. Das Python-Tutorial weist ausdrücklich darauf hin, dass dies nicht immer die Stelle ist, die korrigiert werden muss. Eine fehlende schließende Klammer fällt zum Beispiel oft erst in einer späteren Zeile auf. Prüfe deshalb auch die Zeilen davor.

Laufzeitfehler

Das Programm startet, bricht aber während der Ausführung ab, etwa beim Zugriff auf ein Element, das es nicht gibt, oder bei einer Division durch null. Hier fragst du: Mit welchen Werten arbeitet die betroffene Zeile, und kann eine Eingabe leer sein oder einen anderen Typ haben, als der Code annimmt?

Logikfehler

Das Programm läuft durch, aber das Ergebnis stimmt nicht. Weil keine Meldung erscheint, sind diese Fehler oft am schwersten zu finden. Du vergleichst Zwischenergebnisse mit dem, was du erwartest, und gehst jede Bedingung durch: Welchen Wert hat sie, welchen Zweig nimmt das Programm?

Ein Beispiel: der falsche Durchschnitt

Diese Funktion soll den Durchschnitt einer Liste berechnen:

Python
def durchschnitt(werte):
    summe = werte[0] + werte[1]
    return summe / len(werte)

print(durchschnitt([2, 4, 6]))
Text
2.0

Erwartet war 4.0. Statt zu raten, machst du die Werte sichtbar. Eine zusätzliche Ausgabe vor der Rückgabe zeigt, was die Funktion tatsächlich rechnet:

Python
def durchschnitt(werte):
    summe = werte[0] + werte[1]
    print(f"DEBUG werte={werte} summe={summe} anzahl={len(werte)}")
    return summe / len(werte)

print(durchschnitt([2, 4, 6]))
Text
DEBUG werte=[2, 4, 6] summe=6 anzahl=3
2.0

Die Summe ist 6 statt 12: Der Fehler liegt nicht in der Division, sondern in der Summe, die nur die ersten beiden Werte addiert. Die Korrektur ist sum(werte). Danach prüfst du nicht nur den ursprünglichen Fall, sondern auch einen Grenzfall, die leere Liste:

Python
def durchschnitt(werte):
    summe = sum(werte)
    return summe / len(werte)

print(durchschnitt([2, 4, 6]))
print(durchschnitt([]))
Text
4.0
Traceback (most recent call last):
  File "durchschnitt.py", line 6, in <module>
    print(durchschnitt([]))
          ~~~~~~~~~~~~^^^^
  File "durchschnitt.py", line 3, in durchschnitt
    return summe / len(werte)
           ~~~~~~^~~~~~~~~~~~
ZeroDivisionError: division by zero

Der erste Fall stimmt jetzt, der zweite deckt eine neue Frage auf: Was soll bei einer leeren Liste passieren? Ob die Funktion dann einen verständlichen Fehler auslöst oder einen festgelegten Wert zurückgibt, ist deine Entscheidung. Wichtig ist, dass du sie bewusst triffst. Wie Funktionen und Listen in Python funktionieren, steht in den Python-Grundlagen.

Fehlermeldungen richtig lesen

Der Traceback oben ist typisch für Python. „most recent call last" bedeutet: Der zuletzt ausgeführte Aufruf steht unten. Lies ihn deshalb von unten nach oben. Ganz unten stehen Fehlertyp und Meldung (ZeroDivisionError: division by zero), darüber die Zeile, in der es passiert ist (Zeile 3 in durchschnitt), und darüber, von wo diese Funktion aufgerufen wurde (Zeile 6). Die Zeichen ~ und ^ unter den Codezeilen heben die betroffene Stelle im Ausdruck hervor.

Node.js ordnet umgekehrt. Dieses JavaScript-Beispiel greift auf das erste Element einer leeren Liste zu:

JavaScript
function ersterName(kunden) {
  return kunden[0].name.toUpperCase();
}

console.log(ersterName([{ name: "Ada" }]));
console.log(ersterName([]));
Text
ADA
kunden.js:2
  return kunden[0].name.toUpperCase();
                   ^

TypeError: Cannot read properties of undefined (reading 'name')
    at ersterName (kunden.js:2:20)
    at Object.<anonymous> (kunden.js:6:13)

Hier stehen Fehlertyp und Meldung oben, darunter die Aufrufe vom innersten zum äußersten: zuerst ersterName in Zeile 2, dann der Aufruf in Zeile 6. Die Meldung sagt wörtlich, was los ist: kunden[0] ist undefined, und von undefined lässt sich keine Eigenschaft name lesen.

In beiden Sprachen gilt: Die genannte Zeile ist ein guter Startpunkt, aber nicht zwingend der Ursprung. Oft bekommt eine Funktion einen ungültigen Wert, der ganz woanders entstanden ist. Prüfe deshalb, woher die Daten stammen, die an der Fehlerstelle ankommen.

Werkzeuge: Ausgaben und Haltepunkte

Für den Einstieg reicht oft eine gezielte Ausgabe wie oben, in Python mit print(), in JavaScript mit console.log(). Entferne solche Diagnoseausgaben wieder, wenn du sie nicht mehr brauchst.

Bei größeren Programmen hilft ein Debugger. Er hält die Ausführung an einem Haltepunkt (Breakpoint) an, sodass du Variablen ansehen und den Code Schritt für Schritt weiterlaufen lassen kannst. In Python setzt du einen Haltepunkt, indem du breakpoint() in den Code schreibst; laut Python-Dokumentation startet das den eingebauten Debugger pdb. Node.js bringt einen Kommandozeilen-Debugger mit, den du mit node inspect datei.js startest; die Anweisung debugger; im Code markiert dort einen Haltepunkt. Editoren und Entwicklungsumgebungen bieten dieselben Funktionen grafisch an; wie sie bedient werden, steht in ihrer Dokumentation.

Ausgaben und Haltepunkte helfen nur mit einer konkreten Frage. Statt alle Variablen anzusehen, frag zum Beispiel: Welchen Wert hat diese Variable direkt vor der Bedingung?

Den Fehler eingrenzen

Wenn die Ursache nicht offensichtlich ist, verkleinerst du den Suchraum:

  • Minimales Beispiel: Entferne Schritt für Schritt alles, was für den Fehler nicht nötig ist, bis nur noch wenige Zeilen übrig sind, die ihn auslösen. Oft findest du die Ursache schon dabei.
  • Halbieren: Prüfe in der Mitte des Ablaufs, ob die Werte noch stimmen. Stimmen sie, liegt der Fehler dahinter, sonst davor. Dann halbierst du den verbleibenden Teil erneut.
  • Im Verlauf suchen: Funktionierte der Code früher, hilft git bisect. Das Kommando nutzt laut Git-Dokumentation eine binäre Suche, um den Commit zu finden, der einen Fehler eingeführt hat: Du markierst einen guten und einen schlechten Stand, Git checkt jeweils einen Commit dazwischen aus, und du meldest, ob der Fehler dort auftritt. Die Grundlagen zu Commits und Branches stehen im Artikel zu Git-Befehlen.
  • Laut erklären: Erkläre den Code Zeile für Zeile, notfalls einer Gummiente auf dem Schreibtisch. Beim Erklären fällt oft die Stelle auf, an der deine Annahme nicht mit dem Code übereinstimmt.

Gute Fragen stellen und Antworten prüfen

Kommst du allein nicht weiter, frag in einem Forum, im Team oder bei einem KI-Assistenten. Eine gute Frage enthält: was du erwartest, was tatsächlich passiert, die vollständige Fehlermeldung, die Schritte zum Auslösen, dein minimales Beispiel und was du schon probiert hast. Entferne vorher Passwörter, Schlüssel und personenbezogene Daten.

Antworten, auch die eines KI-Assistenten, sind Hypothesen, keine Lösungen. Prüfe sie wie jede andere Änderung: Verstehe, warum der Vorschlag den Fehler beheben soll, ändere nur das, führe den ursprünglichen Fall und die Grenzfälle erneut aus.

Wichtig: Wenn eine Änderung nichts bewirkt, mach sie rückgängig, bevor du die nächste versuchst. Mehrere ungeprüfte Änderungen übereinander machen aus einem Fehler oft zwei.

Typische Stolperfallen

  • Zu viel auf einmal ändern: Die Wirkung einzelner Änderungen ist dann nicht mehr erkennbar.
  • Die erste plausible Erklärung glauben: Prüfe, ob sie alle Beobachtungen erklärt.
  • Nur die Fehlerstelle ansehen: Verfolge Werte zurück bis dorthin, wo sie entstehen.
  • Grenzfälle übersehen: Leere Eingaben, Grenzwerte und unerwartete Typen nehmen oft einen anderen Weg durch den Code.
  • Die Korrektur nicht erneut prüfen: Führe nach der Änderung den ursprünglichen Fall und weitere passende Fälle aus.

Dein nächster Schritt

Nimm das Durchschnitts-Beispiel, entscheide, was bei einer leeren Liste passieren soll, und setze es um. Füge danach breakpoint() vor die Rückgabe ein, starte das Skript und lass dir im Debugger mit p summe den Wert der Variablen anzeigen. Wenn du einen Fehler in einer HTML-Seite suchst, hilft dir zusätzlich der Artikel HTML lernen; alle Grundlagen-Artikel findest du im Ressort Programmierung.

Häufige Fragen

Muss ich jede Fehlermeldung sofort vollständig verstehen?

Nein. Beginne mit dem Fehlertyp, der Meldung und der Zeile, in der das Problem sichtbar wird. Unbekannte Begriffe schlägst du in der Dokumentation der Programmiersprache nach.

Was tun, wenn der Fehler nur manchmal auftritt?

Notiere genau, wann er erscheint und welche Eingaben und Schritte vorausgehen. Achte auf Unterschiede im Startzustand, in der Reihenfolge von Aktionen und in den Daten; erst wenn du ihn gezielt auslösen kannst, lohnt die eigentliche Suche.

Wann sollte ich andere um Hilfe bitten?

Sobald du das Problem eingegrenzt und deine Beobachtungen notiert hast. Dann kannst du erwartetes und tatsächliches Verhalten, die Schritte zum Auslösen und dein minimales Beispiel nennen; vertrauliche Daten und Zugangsdaten gehören nicht in die Frage.

Quellen

  1. Errors and Exceptions (The Python Tutorial) Python-Dokumentation (python.org) · abgerufen am 13. November 2026
  2. pdb — The Python Debugger Python-Dokumentation (python.org) · abgerufen am 13. November 2026
  3. Debugger Node.js-Dokumentation (nodejs.org) · abgerufen am 13. November 2026
  4. git-bisect git-scm.com · abgerufen am 13. November 2026