You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/08/30 04:15:08 UTC
(texera) 01/01: fix(agent-service): handle falsy model throws (#7638)
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 <an...@gmail.com>
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 bun@1.3.14 test src/agent/texera-agent.spec.ts
npx --yes bun@1.3.14 run typecheck
npx --yes bun@1.3.14 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;