Bug: ToolMessage status field not set by ToolNode despite type definition #312

Open
opened 2026-02-15 18:15:47 -05:00 by yindo · 1 comment
Owner

Originally created by @MH4GF on GitHub (Jul 24, 2025).

Checked other resources

  • I added a very descriptive title to this issue.
  • I searched the LangGraph.js documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangGraph.js rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).

Example Code

The following code:

import { ToolNode } from "@langchain/langgraph/prebuilt";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { AIMessage } from "@langchain/core/messages";

// Success tool
const successTool = tool(() => "Success result", {
  name: "success_tool",
  schema: z.object({ input: z.string() }),
});

// Error tool
const errorTool = tool(() => {
  throw new Error("Tool error");
}, {
  name: "error_tool", 
  schema: z.object({ input: z.string() }),
});

const toolNode = new ToolNode([successTool, errorTool]);

async function testStatus() {
  // Test success case
  const successMsg = new AIMessage({
    content: "",
    tool_calls: [{ name: "success_tool", args: { input: "test" }, id: "1", type: "tool_call" }]
  });
  const successResult = await toolNode.invoke({ messages: [successMsg] });
  console.log("Success status:", successResult.messages[0].status); // Expected: "success", Actual: undefined

  // Test error case  
  const errorMsg = new AIMessage({
    content: "",
    tool_calls: [{ name: "error_tool", args: { input: "test" }, id: "2", type: "tool_call" }]
  });
  const errorResult = await toolNode.invoke({ messages: [errorMsg] });
  console.log("Error status:", errorResult.messages[0].status); // Expected: "error", Actual: undefined
}

testStatus();

Error Message and Stack Trace (if applicable)

No error is thrown, but the status field remains undefined when it should be "success" or "error".

Description

The ToolMessage type definition includes a status field (status?: "error" | "success" | undefined) that was added in commit da3a1a862 (Feb 8, 2025), but the ToolNode implementation does not set this field when creating ToolMessage instances.

What I was trying to do:
Access the status field on ToolMessage to determine if a tool call succeeded or failed.

What I expected to happen:

  • When a tool executes successfully, status should be "success"
  • When a tool execution fails, status should be "error"

What actually happened:
The status field is always undefined because the ToolNode implementation (in /libs/langgraph/src/prebuilt/tool_node.ts lines 182-187 and 200-204) does not explicitly set the status field when creating ToolMessage instances.

Impact:
This creates a discrepancy between the type system (which suggests the field should be populated) and the runtime behavior (where it's always undefined), making it impossible to programmatically determine tool execution status.

System Info

Platform: Darwin 23.4.0
Node version: v24.2.0
Package Manager: pnpm 10.12.1

Package Info

@langchain/community 0.3.49
@langchain/core 0.3.62
@langchain/langgraph 0.3.10
@langchain/openai 0.5.18
Originally created by @MH4GF on GitHub (Jul 24, 2025). ### Checked other resources - [x] I added a very descriptive title to this issue. - [x] I searched the LangGraph.js documentation with the integrated search. - [x] I used the GitHub search to find a similar question and didn't find it. - [x] I am sure that this is a bug in LangGraph.js rather than my code. - [x] The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package). ### Example Code The following code: ```ts import { ToolNode } from "@langchain/langgraph/prebuilt"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { AIMessage } from "@langchain/core/messages"; // Success tool const successTool = tool(() => "Success result", { name: "success_tool", schema: z.object({ input: z.string() }), }); // Error tool const errorTool = tool(() => { throw new Error("Tool error"); }, { name: "error_tool", schema: z.object({ input: z.string() }), }); const toolNode = new ToolNode([successTool, errorTool]); async function testStatus() { // Test success case const successMsg = new AIMessage({ content: "", tool_calls: [{ name: "success_tool", args: { input: "test" }, id: "1", type: "tool_call" }] }); const successResult = await toolNode.invoke({ messages: [successMsg] }); console.log("Success status:", successResult.messages[0].status); // Expected: "success", Actual: undefined // Test error case const errorMsg = new AIMessage({ content: "", tool_calls: [{ name: "error_tool", args: { input: "test" }, id: "2", type: "tool_call" }] }); const errorResult = await toolNode.invoke({ messages: [errorMsg] }); console.log("Error status:", errorResult.messages[0].status); // Expected: "error", Actual: undefined } testStatus(); ``` ### Error Message and Stack Trace (if applicable) No error is thrown, but the status field remains undefined when it should be "success" or "error". ### Description The `ToolMessage` type definition includes a `status` field (`status?: "error" | "success" | undefined`) that was added in commit da3a1a862 (Feb 8, 2025), but the `ToolNode` implementation does not set this field when creating `ToolMessage` instances. **What I was trying to do:** Access the `status` field on `ToolMessage` to determine if a tool call succeeded or failed. **What I expected to happen:** - When a tool executes successfully, `status` should be `"success"` - When a tool execution fails, `status` should be `"error"` **What actually happened:** The `status` field is always `undefined` because the `ToolNode` implementation (in `/libs/langgraph/src/prebuilt/tool_node.ts` lines 182-187 and 200-204) does not explicitly set the `status` field when creating `ToolMessage` instances. **Impact:** This creates a discrepancy between the type system (which suggests the field should be populated) and the runtime behavior (where it's always undefined), making it impossible to programmatically determine tool execution status. ### System Info **Platform:** Darwin 23.4.0 **Node version:** v24.2.0 **Package Manager:** pnpm 10.12.1 ## Package Info ``` @langchain/community 0.3.49 @langchain/core 0.3.62 @langchain/langgraph 0.3.10 @langchain/openai 0.5.18 ```
yindo added the bug label 2026-02-15 18:15:47 -05:00
Author
Owner

@MH4GF commented on GitHub (Jul 24, 2025):

I am interested in creating a PR. I would like to work on it if you are willing.
Thanks.

@MH4GF commented on GitHub (Jul 24, 2025): I am interested in creating a PR. I would like to work on it if you are willing. Thanks.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#312