DEV Community

Cover image for How I Spent 30 Rounds Debugging a "Syntax Error" That Wasn't
chicagoist
chicagoist

Posted on

How I Spent 30 Rounds Debugging a "Syntax Error" That Wasn't

Or: why node --check is not a test.


Recently, I was debugging a JavaScript file with an AI coding agent. It applied string replacements, balanced braces, re-ran node --check — 30 times. When the parser finally said "OK", it declared victory.

Everything was still broken.

The buttons didn't work. The live evaluation didn't fire. The quiz was dead.


The Bug

The entire interactive logic was wrapped in:

const boxes = document.querySelectorAll('.answerbox[contenteditable="true"]');
if (boxes.length > 0) {
  // ALL quiz logic:
  //   event listeners, validation, live highlighting,
  //   save/load, check/clear buttons
}
Enter fullscreen mode Exit fullscreen mode

The .answerbox[contenteditable] elements had been removed during a UI migration to checkboxes. boxes.length was always 0. The condition was always false.

The code was syntactically perfect. Logically dead.

node --check said: ✅ PASS. The browser said: ❌ nothing works.

This isn't just about this one quiz — dead guards after UI migration are one of the most common causes of "parses but doesn't run" bugs in any frontend project.


The Real Problem

The debugging methodology was:

1. See SyntaxError
2. Fix braces
3. node --check passes
4. "Fixed!"
Enter fullscreen mode Exit fullscreen mode

Step 4 was wrong. The parser is not a test suite.


The Fix: Control-Flow Verification Rule

A mandatory three-check rule that runs after node --check passes:

# Check Action
1 DOM cross-reference For every querySelector(All), verify the target exists in the HTML body
2 Execution-path trace From IIFE entry, trace to every addEventListener — verify reachable
3 boxes.length > 0 pattern Any guard wrapping >10 lines of logic after a UI migration is a red flag

With these three checks, the bug is found in 3 steps instead of 30 rounds.

why  raw `node --check` endraw  is not a test


The Meta-Rule

Syntax ≠ logic. node --check, tsc --noEmit, or any parser pass does NOT mean the code works. Always verify that code executes, not just that it parses.

Syntax ≠ Logic


Real Impact

I submitted two PRs to Codebuff (the open-source AI coding agent behind Freebuff) to encode these rules into the agent's system prompt:

If merged, every future session of the Buffy agent will automatically apply these checks before declaring a JS fix complete.


Your Turn

Ever been burned by a dead if (elements.length > 0) guard? What's your go-to check after node --check passes?


This bug was found during cybersecurity coursework (BSI Grundschutz, NIS-2 Webinar). The debugging methodology was developed in collaboration between a human student and the AI agent itself.


Tags

#javascript #debugging #ai #codebuff #softwareengineering #webdev #opensource #devtools


Top comments (0)