fix: bubble real dbt show error instead of generic "Could not parse"#931
fix: bubble real dbt show error instead of generic "Could not parse"#931sahrizvi wants to merge 2 commits into
Conversation
…ot parse" `execDbtShow` swallowed `run()` rejections silently — when `dbt show` crashed (e.g. corrupted `dbt_packages/*`, missing `dbt_project.yml`, DB connection refused), the agent saw a misleading "Could not parse dbt show output in any format" message and treated it as transient. The real `Runtime Error: ...` from `dbt`'s stderr never surfaced. Capture the `execFile` rejection's `.stderr` and `.stdout`, scan recovered JSON log lines for `level: "error"` events (dbt with `--log-format json` emits structured error events even on crash), and surface the real error. Preserve the existing generic message only when both `run()` invocations exit 0 but the output is genuinely unparseable — the condition the message was actually designed for. - src/dbt-cli.ts: 2 catch blocks now retain the error; new `extractDbtError()` helper picks structured event > stderr > message. - test/dbt-cli.test.ts: 6 new cases (real stderr surfaces, structured event preferred, ENOENT fallback, generic message preserved on exit-0 unparseable). 24/24 pass. Scoped to `execDbtShow`. `execDbtCompile` and `execDbtCompileInline` share the same masking pattern but have manifest.json / `--quiet` fallbacks that reduce impact — addressed separately if needed.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthrough
ChangesEnhanced dbt Show Error Handling
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
2 similar comments
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/dbt-tools/src/dbt-cli.ts (1)
59-64:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical:
run()does not attach stdout/stderr to the rejection error.Node.js
execFilecallback receives(err, stdout, stderr)as separate arguments. When rejecting witherr, the stdout/stderr are discarded. The new error-extraction logic inexecDbtShowexpectsprimaryRunError.stdoutandprimaryRunError.stderrto be available, but they will beundefinedin production.The tests pass because they manually attach
.stdout/.stderrto the mock error object, but this doesn't match actual Node.js behavior.🐛 Proposed fix to attach stdout/stderr to the error
function run(args: string[]): Promise<{ stdout: string; stderr: string }> { const dbt = getDbt() const env = buildDbtEnv(dbt) const cwd = globalOptions.projectRoot ?? process.cwd() return new Promise((resolve, reject) => { execFile(dbt.path, args, { timeout: 120_000, maxBuffer: 10 * 1024 * 1024, env, cwd }, (err, stdout, stderr) => { - if (err) reject(err) + if (err) { + // Attach stdout/stderr to the error for downstream error extraction (AI-7082) + ;(err as any).stdout = stdout + ;(err as any).stderr = stderr + reject(err) + } else resolve({ stdout, stderr }) }) }) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/dbt-tools/src/dbt-cli.ts` around lines 59 - 64, The Promise returned by run() rejects with the execFile error but currently drops stdout/stderr, so downstream code like execDbtShow can't inspect process output; modify the execFile callback inside run() to attach stdout and stderr onto the err object before rejecting (e.g., set err.stdout = stdout and err.stderr = stderr) and then reject(err), ensuring stdout/stderr are available on the thrown error; reference the run() function and the execFile callback in dbt-cli.ts when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/dbt-tools/src/dbt-cli.ts`:
- Around line 59-64: The Promise returned by run() rejects with the execFile
error but currently drops stdout/stderr, so downstream code like execDbtShow
can't inspect process output; modify the execFile callback inside run() to
attach stdout and stderr onto the err object before rejecting (e.g., set
err.stdout = stdout and err.stderr = stderr) and then reject(err), ensuring
stdout/stderr are available on the thrown error; reference the run() function
and the execFile callback in dbt-cli.ts when making this change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f0e93fb1-a4ae-4eea-b177-6e6589a4ad5f
📒 Files selected for processing (2)
packages/dbt-tools/src/dbt-cli.tspackages/dbt-tools/test/dbt-cli.test.ts
altimate-code is tracked on GitHub, not Jira. Remove the `AI-7082` labels from code comments, test names, and the section header — the PR description carries the cross-reference instead. No functional changes; 24/24 bun:test still pass.
Closes #932
Summary
altimate-dbt execute --query "..."(which callsexecDbtShowinpackages/dbt-tools/src/dbt-cli.ts) swallows the real error fromdbt showand surfaces a misleading generic message:{ "error": "Could not parse dbt show output in any format (JSON, heuristic, or plain text). Got 0 JSON lines.", "fix": "Run: altimate-dbt doctor" }But running
dbt showdirectly produces a clear actionable error, e.g.:The real error never reaches the caller. Agents read "could not parse" as transient and retry alternate commands instead of bailing out — burns budget on a project that is structurally broken.
Root cause
packages/dbt-tools/src/dbt-cli.tshas two adjacent catch blocks inexecDbtShowthat swallow therun()rejection silently:When
execFilerejects with a non-zero exit, the error object carries.stderrand.stdout. Both catches discard them. The generic "Could not parse" message was designed for the case "dbt exited 0 but the output is unparseable" — but it currently fires for the "dbt actually crashed" case as well, conflating two very different failure modes.Fix
execFilerejection on both tiers (primaryRunError,plainRunError).stdout— dbt with--log-format jsonemits structuredlevel: "error"events before exit.extractDbtError(...)which picks (in order): structured error event > primary stderr > plain stderr > exception message.extractDbtErrorreturns anything, surface it asdbt show failed: <real msg>. Fall through to the generic message only when both runs exited 0.Net: ~45 lines in
dbt-cli.ts(helper + 2 small guard sites), 6 new test cases.Scope
Limited to
execDbtShow.execDbtCompileandexecDbtCompileInlineshare the samecatch { lines = [] }pattern but have additional fallback paths (manifest.json for compile, no-args plain-text retry for inline) that reduce caller impact. Worth addressing in a follow-up PR if telemetry shows masking there too — kept out of this PR to keep the diff focused.Test plan
bun test test/dbt-cli.test.ts→ 24/24 pass (18 pre-existing + 6 new)dbt showexits 0 but emits unparseable output (regression guard preserved)dbt showsurfaces in the thrown errorlevel: "error"event preferred over raw stderr when both presentspawn ENOENT(no dbt binary) surfaces clearlydbt_packages/<pkg>/dbt_project.yml; expect to see the real "Failed to read package" message, not "Could not parse"Links
03-issues-and-fixes.mdIssue docs: rewrite README for open-source launch #14dbt_packages/fixtureSummary by CodeRabbit