This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7638-50dd7d5969e746ff02b11af240a4067d4a96e3ba in repository https://gitbox.apache.org/repos/asf/texera.git
commit 14a574f0cfd6feab99c90b58fb1492ce76d68b15 Author: anthonychengit <[email protected]> AuthorDate: Sun Aug 30 03:41:16 2026 +0000 fix(agent-service): handle falsy model throws (#7638) ### What changes were proposed in this PR? The model adapter can throw arbitrary JavaScript values, including `null` and `undefined`. The previous error path immediately read `error.name`, so those values caused `sendMessage` itself to reject instead of returning Texera's normal error result. ```text Before: falsy model throw -> error.name dereference -> rejected sendMessage After: falsy model throw -> normalized error text -> resolved ReAct error step ``` This change safely normalizes thrown values and uses optional access for optional error metadata. The regression test covers `null`, `undefined`, `false`, `0`, and the empty string, and verifies both the resolved response and its recorded error step. ### Any related issues, documentation, discussions? Closes #7485 ### How was this PR tested? ```bash npx --yes [email protected] test src/agent/texera-agent.spec.ts npx --yes [email protected] run typecheck npx --yes [email protected] run format:check ``` The test file passed 56 tests. Type checking and formatting checks also passed. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: OpenAI Codex (GPT-5) --- agent-service/src/agent/texera-agent.spec.ts | 19 +++++++++++++++++++ agent-service/src/agent/texera-agent.ts | 7 ++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/agent-service/src/agent/texera-agent.spec.ts b/agent-service/src/agent/texera-agent.spec.ts index 416fee5444..52d9103866 100644 --- a/agent-service/src/agent/texera-agent.spec.ts +++ b/agent-service/src/agent/texera-agent.spec.ts @@ -670,6 +670,25 @@ describe("sendMessage", () => { expect(agent.getAllSteps()[1].content).toBe("Error: just-a-string"); }); + test.each([null, undefined, false, 0, ""])("a falsy throw resolves as an error step: %p", async thrown => { + const model = new MockLanguageModelV4({ + doGenerate: async () => { + throw thrown; + }, + }); + const agent = makeAgentWith(model); + const res = await agent.sendMessage("hi"); + const expected = String(thrown); + expect(res).toEqual({ + response: "", + messages: [], + usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }, + stopped: false, + error: expected, + }); + expect(agent.getAllSteps()[1].content).toBe(`Error: ${expected}`); + }); + test("a failed turn stays on the branch", async () => { const model = new MockLanguageModelV4({ doGenerate: async () => { diff --git a/agent-service/src/agent/texera-agent.ts b/agent-service/src/agent/texera-agent.ts index ccd0545919..9a640aaab6 100644 --- a/agent-service/src/agent/texera-agent.ts +++ b/agent-service/src/agent/texera-agent.ts @@ -657,7 +657,8 @@ export class TexeraAgent { stopped: false, }; } catch (error: any) { - const isAborted = error.name === "AbortError" || this.abortController?.signal.aborted; + const errorMessage = error?.message || String(error); + const isAborted = error?.name === "AbortError" || this.abortController?.signal.aborted; if (isAborted) { stepIndex++; @@ -693,7 +694,7 @@ export class TexeraAgent { stepId: stepIndex, timestamp: Date.now(), role: "agent", - content: `Error: ${error.message || String(error)}`, + content: `Error: ${errorMessage}`, isBegin: false, isEnd: true, }; @@ -705,7 +706,7 @@ export class TexeraAgent { messages: [], usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }, stopped: false, - error: error.message || String(error), + error: errorMessage, }; } finally { this.abortController = null;
