Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/core/src/common/llm-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,19 @@ function getErrorDetails(error: unknown, depth: number, seen: Set<object>): LlmE
}

function getProviderMessage(error: unknown): string | undefined {
if (!isRecord(error) || !isRecord(error.error)) {
if (!isRecord(error)) {
return undefined;
}
return safeText(error.error.message);
// Providers and gateways do not agree on the error payload shape: some send
// an object with `message`, others send the message as a plain string.
const payload = error.error;
if (typeof payload === "string") {
return safeText(payload);
}
if (!isRecord(payload)) {
return undefined;
}
return safeText(payload.message);
}

function getHeader(headers: unknown, name: string): string | undefined {
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/tests/llm-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ test("describeLlmError shows provider business errors with trace metadata", () =
);
});

test("describeLlmError keeps provider errors whose payload is a plain string", () => {
const error = Object.assign(new Error("502 Bad Gateway"), {
status: 502,
error: "Gateway failed",
headers: new Headers({
"x-request-id": "request-789",
}),
});

assert.equal(describeLlmError(error), "HTTP 502: Gateway failed [request ID: request-789]");
});

test("describeLlmError unwraps underlying network causes", () => {
const cause = new Error("getaddrinfo ENOTFOUND api.deepseek.com");
const error = Object.assign(new Error("Connection error."), { cause });
Expand Down