De grootste ergernis die developers in het Stack Overflow-onderzoek van 2025 noemden, was AI-output die bijna klopt, maar net niet. Zesenzestig procent van hen. De tweede, met 45%, was dat het debuggen van AI-code langer duurt dan het debuggen van je eigen werk. Het vertrouwen in de nauwkeurigheid van AI-tools zakte in een jaar van 40% naar 29%, en 3% zegt er groot vertrouwen in te hebben.
De luidste klacht in het vak gaat dus over debuggen, en wat er als oplossing wordt verkocht, is nog een agent.
En toch. Gisteren vond een agent binnen anderhalve minuut een null in een serializer, in een bestand waar ik twintig minuten naar had zitten staren. Hij had gelijk. Hij had gelijk over iets waar ik zelf ook wel op was uitgekomen, via de saaie route.
Allebei waar. De vraag die je verder helpt, is welke helft van het debuggen je weggeeft.
Waar een agent echt beter in is
Breedte, en uithoudingsvermogen voor het saaie deel.
Een stack trace die veertig bestanden raakt, is voor mij vervelend werk en kost de agent niets. Elke aanroep van een functie opzoeken en stuk voor stuk naast het contract leggen, of de broncode van een dependency lezen in plaats van te gokken wat hij doet: dat is echt werk dat ik oversla als ik moe ben, en hij slaat het niet over.
Hij heeft ook geen ego dat hij moet beschermen. Ik verdedig mijn eigen architectuur zonder dat ik het doorheb. Hij leest mijn slimme stukje code net zo neutraal als de rest, wat af en toe vernederend is en meestal nuttig.
Dat is de mechanische helft van het zoeken naar de oorzaak. Die mag je weggeven. De vraag is wat er met de andere helft gebeurt.
Waar debuggen met AI misgaat
Er is een onderzoek dat die vraag beter beantwoordt dan welke blogpost dan ook, inclusief deze.
Een team draaide 750.013 fault localization-taken met tien modellen op ruim 1.300 echte Java- en Python-programma's (arXiv 2504.04372). Ze bouwden fouten in, hielden alleen de programma's over waarin een model de fout daadwerkelijk vond, en pasten daarna semantic-preserving mutaties toe: wijzigingen die niets veranderen aan wat het programma doet.
Dode code. Misleidende comments. Misleidende variabelenamen. Functies in een andere volgorde.
Vervolgens misten de modellen in 78% van de gevallen de fout die ze daarvoor wél hadden gevonden.
De uitsplitsing per mutatie is nog vervelender dan dat ene getal:
| Toegepaste mutatie | Nauwkeurigheid die overblijft |
|---|---|
| Misleidende variabelenamen | 29,02% |
| Misleidende comments | 25,63% |
| Dode code toegevoegd | 20,38% |
| Functies herordend (Java) | 17% |
Lees dat rijtje nog eens als beschrijving in plaats van als experiment. Dode code. Comments die niet meer kloppen. Namen die liegen over wat het ding doet. Functies in de volgorde waarin ze erbij zijn geplakt in plaats van de volgorde waarin ze draaien.
Die mutaties beschrijven elke codebase die drie jaar heeft gedraaid.
Hetzelfde onderzoek laat zien dat 56% van de fouten die de modellen vinden in het eerste kwart van de code zit, en 6% in het laatste kwart. De onderkant van je bestand wordt nauwelijks doorzocht. En bij de nieuwere Claude- en Gemini-versies die ze testten ging de fault localizability één tot twee procent omhoog, dus wachten op het volgende model helpt je hier niet.
Omvang doet daar nog een schepje bovenop. LinuxFLBench zette agents op 250 echte bugs in de Linux-kernel, in een tree van 69.000 bestanden en 28 miljoen regels (arXiv 2505.19489). De beste, SWE-Agent, kwam uit op een Recall@1 van 0,416.
Het scherpste punt van het paper zit in het verschil: dezelfde agents scoren 16,7% tot 31,9% hoger op software van normale omvang. Tot een derde van de nauwkeurigheid verdwijnt puur door de omvang.
En bij de bugs waar je de meeste hulp bij kunt gebruiken, regressies, zijn de cijfers om te beginnen ronduit somber. Op RegMiner4APR, 99 regressies uit 32 repositories, scoorden de klassieke repair-tools 0%. De beste LLM-aanpak leverde in 9% van de gevallen een correcte patch op (arXiv 2506.13182).
Daarna vertelden de onderzoekers het model welke commit de bug had geïntroduceerd.
Zestien procent. Bijna een verdubbeling, door één feit dat de hele tijd in git log stond.
Al die missers komen door ontbrekende informatie
Dat is de rode draad door alle drie de papers, en het is de basis onder een hele werkwijze.
Het model heeft redeneervermogen genoeg. Wat het mist, zijn de feiten die de zoekruimte kleiner maken en die jij al hebt: welke commit, welk subsysteem, welke naam in dit bestand op dit moment staat te liegen. Geef die erbij, en de cijfers gaan omhoog. Houd ze achter en je krijgt stellige output die naar de bovenkant van het verkeerde bestand wijst.
Daarmee krijg je een werkverdeling die niets te maken heeft met hoe moeilijk de bug is.
Jij bakent af en stelt de hypothese op. Hij zoekt en toetst.
Zo draag je een bug over
Reproduceer hem eerst zelf. Een bug die je niet op commando kunt uitlokken, is een bug waarvan je de fix niet kunt verifiëren, en de agent geeft je met alle plezier een patch die het symptoom laat verdwijnen. Kost dat reproduceren een uur, dan is dat uur het werk, en dat kun je niet uitbesteden.
Baken de zoekruimte af vóór je overdraagt. Noem het subsysteem, de module, de laag. De verbetering in het kernel-onderzoek kwam puur van een kleinere zoekruimte. Jij weet in welke helft van het systeem dit zit. Dat opschrijven levert meer op dan welke prompttruc dan ook.
Geef hem naast de error ook de diff. git log -S, de laatste groene deploy, de commit die aan dit pad heeft gezeten. Dat is de sprong van 9% naar 16% uit het paper, en bij een regressie vind je die commit meestal zelf.
Vraag eerst om een hypothese, dan pas om een patch. Daar komt steun voor uit onverwachte hoek. De beschrijving van de EnterPlanMode-tool in Claude Code, versie 2.1.224, noemt dit als een geval dat om plannen vraagt:
Unclear Requirements: You need to explore before understanding the full scope
- Example: "Fix the bug in checkout" - need to investigate root cause
De tool rekent een bug met een onbekende oorzaak zelf tot planwerk. Diezelfde beschrijving zegt daarna dat je plannen kunt overslaan bij "obvious bugs, small tweaks", en juist dat oordeel over wat voor de hand ligt, is volgens het mutatieonderzoek precies waar het model slecht in is. Neem die beslissing dus zelf: plan mode vóór de eerste bewerking, en keur de redenering goed in plaats van de diff.
Laat hem na drie pogingen stoppen. De systematic-debugging-skill die ik draai begint met een ijzeren wet, NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST, en met een regel die ik inmiddels nog waardevoller vind: stop na drie mislukte fixes en trek de architectuur in twijfel in plaats van een vierde te proberen. Drie keer achter elkaar mis is informatie. Meestal betekent het dat de bug niet zit waar iedereen kijkt.
Houd de sessie kort. Debuggen is de snelste manier om een contextvenster vol te krijgen: logs, stack traces, hele bestanden erin geplakt om één regel na te kijken. Tegen de tijd dat je bij hypothese vier bent, redeneer je in een sessie waarin het vroege bewijs onderop ligt, en dat is een probleem op zich. Begin vaker opnieuw in een schone sessie dan nodig lijkt.
Wat ik niet weggeef
Bugs waarbij de echte vraag is wat de code hóórde te doen. De agent kan me vertellen wat de code doet. Hij kan me niet vertellen wat er op die factuur had moeten staan, en een stellig antwoord is daar erger dan geen antwoord.
Race conditions, timingbugs, alles waar je slecht zicht op hebt. Beperkte observability is volgens LinuxFLBench een van de drie redenen dat agents op kernelwerk stuklopen. Daarbuiten lopen ze om dezelfde reden stuk.
En alles in code die ik nooit heb gelezen. Dat is het stuk waar ik het langst niet eerlijk over durfde te zijn.
Het gevoel dat je moet vasthouden
Wat er in dat onderzoek misgaat, is een model dat een vloeiend, concreet, goed onderbouwd antwoord geeft over de verkeerde functie, omdat een variabelenaam het model een verhaal vertelde.
De patch ziet er prima uit, dus daar zie je het niet aan. Je merkt het doordat je al ruwweg wist wat die module doet voordat je het vroeg, en dat is een vaardigheid met onderhoudskosten. Die zakt geruisloos weg terwijl je output omhooggaat. Bewust code lezen is het enige dat ik heb gevonden dat die vaardigheid op peil houdt.
Houd een deel van de bugs voor jezelf. Regelmatig eentje, in de systemen die van jou zijn.
De 45% die zegt dat het debuggen van AI-code langer duurt, is niet slecht in prompten. Zij debuggen code die ze nooit hebben gelezen.
De overdracht werkt als jij het leeswerk hebt gedaan.