-
Notifications
You must be signed in to change notification settings - Fork 87
fix: bubble real dbt show error instead of generic "Could not parse" #933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,6 +149,73 @@ describe("execDbtShow", () => { | |
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow("Could not parse dbt show output in any format") | ||
| }) | ||
|
|
||
| // --- Bubble real dbt error instead of generic "Could not parse" --- | ||
|
|
||
| test("surfaces real dbt stderr when run fails", async () => { | ||
| mockExecFile.mockImplementation((_cmd: string, _args: string[], _opts: any, cb: Function) => { | ||
| const err: any = new Error("Command failed: dbt show --inline ...") | ||
| err.code = 1 | ||
| err.stdout = "" | ||
| err.stderr = | ||
| "Runtime Error: Failed to read package: No dbt_project.yml found at expected path dbt_packages/dbt_utils/dbt_project.yml" | ||
| cb(err, err.stdout, err.stderr) | ||
| }) | ||
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow(/Failed to read package/) | ||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow(/dbt show failed/) | ||
| }) | ||
|
|
||
| test("prefers structured error event in JSON log over raw stderr", async () => { | ||
| const errorLog = JSON.stringify({ | ||
| info: { | ||
| level: "error", | ||
| msg: "Compilation Error: Model 'foo' depends on a node named 'bar' which was not found", | ||
| }, | ||
| }) | ||
| mockExecFile.mockImplementation((_cmd: string, _args: string[], _opts: any, cb: Function) => { | ||
| const err: any = new Error("Command failed") | ||
| err.code = 1 | ||
| err.stdout = errorLog | ||
| err.stderr = "exit status 1" | ||
| cb(err, err.stdout, err.stderr) | ||
| }) | ||
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow(/Compilation Error.*Model 'foo'/) | ||
| }) | ||
|
|
||
| test("does not surface generic 'Could not parse' when dbt actually crashed", async () => { | ||
| mockExecFile.mockImplementation((_cmd: string, _args: string[], _opts: any, cb: Function) => { | ||
| const err: any = new Error("Command failed") | ||
| err.code = 2 | ||
| err.stdout = "" | ||
| err.stderr = "Database Error: connection refused" | ||
| cb(err, err.stdout, err.stderr) | ||
| }) | ||
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.not.toThrow(/Could not parse dbt show output/) | ||
| }) | ||
|
|
||
| test("preserves generic 'Could not parse' when dbt exited 0 but output unparseable", async () => { | ||
| // Existing behavior — dbt didn't crash, we just couldn't decode its output. | ||
| mockExecFile.mockImplementation((_cmd: string, _args: string[], _opts: any, cb: Function) => { | ||
| cb(null, "some unparseable output", "") | ||
| }) | ||
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow("Could not parse dbt show output in any format") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Duplicate test: "preserves generic 'Could not parse' when dbt exited 0 but output unparseable" tests the exact same scenario as the existing "Tier 3: throws with helpful message when all tiers fail" test. Both use an identical mock (cb(null, "some unparseable output", "")) and assert the same rejection string. The new test adds zero coverage and creates maintenance overhead — any change to the generic-error path must be kept in sync across two identical tests. Prompt for AI agents |
||
| }) | ||
|
|
||
| test("falls back to error message when stderr is empty", async () => { | ||
| mockExecFile.mockImplementation((_cmd: string, _args: string[], _opts: any, cb: Function) => { | ||
| const err: any = new Error("spawn ENOENT") | ||
| err.code = "ENOENT" | ||
| err.stdout = "" | ||
| err.stderr = "" | ||
| cb(err, "", "") | ||
| }) | ||
|
|
||
| await expect(execDbtShow("SELECT 1")).rejects.toThrow(/spawn ENOENT|dbt show failed/) | ||
| }) | ||
| }) | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.