vibescoder

A Vibe Coder Is Still A Coder: Why, When, and How To Report Bugs

·10 min read

Every so often, your agent’s turn just... ends. No error. No crash. No output. The task was running, the reasoning was visibly happening, and then it stops, and there’s nothing to show for it. Nine times out of ten, the fix is almost insultingly simple: nudge it. Ask it to restate what happened, or just try again. The answer was usually sitting there the whole time, computed and ready, just never delivered.

It’s easy to file that under “flaky UX” and move on, because most of the time that’s exactly what it is — a rendering hiccup, a dropped frame, not worth a second thought. But “usually a hiccup” isn’t the same as “always a hiccup,” and every so often that exact symptom is the visible edge of an actual bug. The only way to tell the difference is to stop and look instead of just nudging past it forever. That’s not a chore bolted onto vibe coding — figuring out why the machine did the odd thing is a big part of what makes it fun in the first place. A vibe coder is still a coder, and that instinct — something’s slightly off, let’s actually find out why — is the same one that’s kept software engineers employed for decades. This post is the why, the when, and the how, using a real hang I ran into this week as the live example.

Why This Is Worth Investigating

A crash tells you where to look. An exception has a stack trace. A failed build has a red line in the output. A stall gives you none of that, which is exactly the trap: the instinct is to read “no error” as “nothing’s wrong, just slow,” and either wait it out or retry.

But something is wrong — the absence of an error is itself the anomaly. Code that’s merely slow usually shows some sign of life: a progress indicator, partial output, something. Code that goes fully silent partway through a task, especially if it happens more than once, is telling you a specific and useful thing: whatever’s failing is failing somewhere the system doesn’t have error handling for. That’s a narrower, more diagnosable claim than “it’s broken,” and it’s worth chasing precisely because most tooling doesn’t hand it to you for free.

The rule of thumb: treat a repeatable stall as a symptom that deserves the same investigative energy as a crash, not less. If your agent session goes silent on a specific kind of request more than once, don’t just nudge harder. Ask it to help you figure out what actually happened.

The Investigation

This week gave me a clean example. Mid-session, working with my coding agent on unrelated homelab housekeeping, calls involving GitHub started going silent — sometimes fine, sometimes nothing, no error either way. My first read was close to the trap above: assume it’s flaky, work around it, keep moving. I told the agent to stop touching “GitHub API or MCP” and stick to the gh CLI instead, which worked immediately and reliably. Problem solved, in the narrow sense.

But “worked around” isn’t the same as “understood,” and a repeatable, tool-specific stall is exactly the kind of signal from the section above that’s worth a second pass. So instead of leaving it as a permanent workaround, I asked the agent to help me actually investigate it — systematically, and without risking the same stall taking down the investigation itself.

Isolating the Failure Without Getting Stuck Investigating It

The obvious problem with debugging a hang directly: if the thing you’re testing hangs, your one investigative session hangs with it. The fix was to spawn the test cases out to independent subagents — five of them, each responsible for one category of the tool calls in question, running in parallel. If one hung, it hung on its own; the other four, and the orchestrating session, kept working. This is the same principle as not debugging a production outage from the one server that’s on fire — get a vantage point that survives the failure you’re trying to observe.

Each subagent got a narrow assignment: call a couple of specific tools from the Model Context Protocol-based GitHub integration that Coder’s AI Gateway bridges into the chat (that’s where the bmcp_ prefix comes from — “bridged MCP” — nothing project-specific about it), and report back exactly what happened: success, an error message, or “no response, gave up.”

CategoryTools calledResult
Identityget_meSuccess, first try
Repo metadatalist_branches, get_file_contents (single file)Success, first try
Searchsearch_code, search_repositoriesEmpty report on first attempt — recovered on a nudge; both calls had actually succeeded
PR/issue readlist_pull_requests, pull_request_read (single PR)Success, first try
Heavy payloadget_commit (full_patch on a real multi-file commit), list_commits (50 results)Empty report, twice in a row — recovered on a third, more terse nudge; both calls had actually succeeded

What Came Back

Every category eventually reported success. That’s the finding worth sitting with for a second — no tool was actually broken, and no GitHub call actually failed. But two of the five subagents — search and heavy payload — came back with a completely empty final report on the first attempt, despite the underlying call having already succeeded. Nudging each one to just restate the result produced the correct answer immediately. The data existed the whole time. Something about producing the final response after ingesting a large or unusually-shaped result was dropping the output, silently, with nothing surfaced as an error anywhere in the chain.

That’s a materially different bug than “the GitHub integration is broken.” It’s specific: response size or shape, not tool identity. And it’s actionable in a way “GitHub stuff sometimes hangs” never would have been.

When It’s Worth Reporting

Not every stall clears this bar, and it shouldn’t — filing a bug for every one-off hiccup wastes everyone’s time, yours included. A few conditions that tip something from “shrug and retry” to “this is worth someone else’s attention”:

  • It’s repeatable, not a one-off. A single unexplained stall is noise. The same category of call failing the same way more than once is signal.
  • You can describe it more specifically than “sometimes it hangs.” If systematic testing gets you to a real correlation — here, payload size/shape rather than tool identity — you have something a maintainer can actually act on.
  • It’s not your own misconfiguration. Worth ruling out first: bad credentials, a genuinely offline dependency, a typo in a config file. This one wasn’t — every underlying call succeeded once you looked past the missing final response.
  • Someone else would hit it too. This wasn’t specific to my environment or my repos; any bridged MCP tool call returning a large or complex result looked exposed to the same failure path.

All four were true here, which is what made this worth filing evidence on rather than just quietly keeping the gh CLI workaround forever.

How To Report It Well

Finding a real, reproducible bug is the fun part. What you do with it next is where a lot of people — myself included, historically — drop the ball. Filing it well is its own discipline, and it’s a well-documented one if you’ve never done it before:

  • Search before you file. A duplicate issue costs a maintainer time twice: once to notice it’s a duplicate, once to close it. A search for the general shape of the problem (not just your exact error text) turned up coder/coder#27178 — same symptom, already open, already tracked internally on Coder’s side. Filing a new issue would have split attention across two threads for no reason. Adding evidence to the existing one didn’t. While I was at it, I also found #24947, the same “MCP failures get silently swallowed” pattern in a different part of the codebase, and #26984, an already-fixed bug in the same general subsystem — worth citing as context, not worth filing separately.
  • Bring reproduction, not just a complaint. “It hangs sometimes” helps nobody. A methodology a maintainer could rerun — the exact tool categories tested, the exact result for each, the correlation with payload size rather than tool identity — is the difference between a comment that gets read and one that gets skipped.
  • State your confidence level honestly. I flagged a hypothesis that this might share a root cause with the already-fixed, unrelated bug in the same subsystem — and said so as a hypothesis, not a claim. Overstating certainty about a codebase you don’t have access to just sends maintainers down a path you can’t actually back up.
  • Redact anything that doesn’t need to be public. No real org names, no tokens, no internal URLs beyond what’s needed to describe the environment (self-hosted, version number, general deployment shape). The bug is reproducible without any of that.
  • Use the channel that actually works. Small thing, but real: gh issue comment failed outright against this specific repo — the coder org has GraphQL access restrictions for third-party OAuth apps — so the comment went in via gh api REST instead. Worth knowing that distinction exists before you assume a CLI failure means your bug report failed to post.
  • Don’t demand a timeline. A comment with evidence is a gift, not a ticket assignment. It’s the maintainer’s call what happens next and when.

None of this is exotic advice. It’s the same etiquette that’s existed around open source bug reports for decades. What’s new is that an agent can now do the tedious middle part — the isolated reproduction, the exact before/after data — fast enough that there’s no excuse not to bring receipts.

What Happens Now

The comment is in on #27178. I’m not going to file a separate tracking mechanism for this or nag the thread — that’s the “don’t demand a timeline” rule applying to myself, not just advice for other people. But I am going to watch it, and when it closes — whether that’s a fix, a “works as intended” with an explanation, or something in between — I’ll report back here so anyone following along gets the actual resolution instead of a dangling thread. Consider this the first half of a two-part story; the second half depends on someone else’s timeline, which is exactly as it should be.

By the Numbers

  • 5 subagents spawned in parallel to isolate the failure without letting it take down the investigation
  • 5 tool categories tested: identity, repo metadata, search, PR/issue read, heavy payload
  • 2 of 5 categories (search, heavy payload) reproduced the empty-response failure
  • 0 underlying GitHub calls that actually failed — every one succeeded server-side
  • 3 nudges it took across both flaky categories to get a real report back
  • 1 existing upstream issue found and contributed to instead of filing a duplicate
  • 2 additional related issues cross-referenced for context, not filed as new
  • 1 GraphQL request that failed outright due to org-level OAuth restrictions, worked around via REST
  • 0 tickets nagged, timelines demanded, or maintainers pinged after the comment posted

Comments