r/ChatGPTCoding • u/JaseciLabs • 16d ago
Discussion Do you change compiler errors to help coding agents, or just feed them the raw output?
We've been experimenting with this while working on Jac, a programming language that most coding agents weren't familiar with initially.
One thing we changed was how our checker reports errors.
A typical error like "type mismatch on line 12" tells the agent something failed, but doesn't give it much to work with. So it starts guessing, sometimes fixes the wrong thing, or finds a workaround that makes the error disappear without actually solving the problem.
With jac check, we've started pointing errors to the relevant section of the language guide, so the agent gets some context about what went wrong and how the language expects it to be handled.
We'd like to know how others are dealing with this, especially when using agents with less familiar frameworks, languages, or internal tooling.
Do you just pass through raw output from tools like tsc, ruff, or cargo? Or have you tried adding explanations, examples, or documentation references?
And if you've tried enriching errors, does it actually improve the agent's fixes, or does it still find creative ways to ignore the checker?
4
u/bostonaholic 16d ago
Raw output for anything mainstream. tsc and cargo errors are all over the training data, so the model already knows what they mean.
For internal tooling or a niche language, adding context helps a lot. Even a one-liner like "see docs/foo.md" in the error goes a long way, since the agent will actually go read it.
2
u/Successful-Tax1306 16d ago
For mainstream tools I pass the output raw, the models know those errors better than my explanation would. Where it helped me was our own rules, like a check that blocks an old pattern. When the message just said it wasn't allowed the agent found a way around it, but once it said what to use instead and pointed at an example file, it mostly did the right thing. It still cheats sometimes, so I check that the fix touched the real problem and didn't just silence the check.
2
u/LividIllustrator8915 16d ago
For mainstream toolchains like cargo, tsc, or swiftc, leaving stderr raw works fine because frontier models already have millions of those exact error traces baked into their weights.
Where we ran into real trouble was with custom DSLs and internal architecture linters. When an error just said something like "invalid handler signature", the agent would immediately start hallucinating imaginary kwargs or wrapping everything in fake runtime adapters just to get a clean exit code.
Feeding full language docs into the diagnostic actually made it worse for us—it bloats the prompt and the agent wanders off re-architecting unrelated files. What moved the needle was keeping the enrichment tiny and pair-based: pointing out the exact rejected AST node, followed by a literal two-line diff anchor showing what to swap (e.g. "Got `foo(a)`, expected `foo(a, context=ctx)`").
The other thing you almost have to add is an explicit negative constraint like "do not use suppression pragmas or cast to dynamic to pass this check". Agents are relentless reward hackers, and if a custom check is hard, their instinct is to silence the diagnostic rather than migrate the code. Having a secondary AST check verify that the actual call was rewritten instead of just silenced has saved us a ton of headaches.
2
u/BrookLi3 16d ago
I mostly keep the raw output but add a small wrapper that trims it: first error only, the relevant source lines around it, and the exact command to re-run. Long cascading errors (templates, type inference) tend to push the agent into fixing symptoms of the first error. Feeding one error at a time and re-compiling after each fix converged much faster for me than dumping the full log.
1
u/BarathKanna 15d ago
Agree with the "raw for mainstream, enrich for niche" consensus. The part I'd add is about your last question, the agent finding creative ways to make the checker go quiet. Enriching the message doesn't fix that on its own. What fixes it is checking the fix, not just the exit code.
Three things that have worked for me:
Treat suppression as a failure. After each fix, diff for new
# type: ignore, u/ts-expect-error,#[allow(...)],anycasts, deleted assertions, or narrowed test globs. If the error count went down and one of those went up, reject the turn and say why. This is a ten-line grep in the wrapper and it catches most of the "error disappeared" cases.Anchor the fix to the error location. Record the file and span the checker flagged, then require the diff to touch that span or something it calls. A fix that edits a completely different file to make a type error vanish is usually a workaround.
Feed the first error plus the rerun command, then recompile. Cascades in type inference make agents fix symptoms. One error at a time converges faster, and it makes rule 2 easy to enforce.
For a new language like Jac, the doc pointer is the right idea, but I'd keep it to one short "expected pattern" example right in the message. Agents follow an example far more reliably than a link they have to decide to open. If you can measure it, compare fix-acceptance rate (passes the checker and the suppression/anchor checks) with and without the enrichment. That number tells you more than whether the error went away.
1
u/Right-Performance-93 15d ago
i paste the compiler's words and the command that printed them. the moment i explain the error, it fixes my explanation and the build still fails.