400 BadRequestError when conversation starts with a tool_call (no assistant/system message) #249

Open
opened 2026-02-15 18:15:01 -05:00 by yindo · 0 comments
Owner

Originally created by @CaillaudPA on GitHub (May 2, 2025).

Description

I'm using createReactAgent from @langchain/langgraph/prebuilt with a custom Postgres-based checkpointSaver for persistence.

I noticed a consistent issue: when the first user message triggers a tool call (e.g. "launch the quiz"), the assistant returns a message with empty content and a tool_calls array.

Everything looks fine at that point — the tool executes correctly, returns a ToolMessage, and the assistant resumes as expected.

However, on the next user message, I get a BadRequestError: 400 status code (no body) from OpenAI. This happens specifically after resuming from a checkpoint, likely due to malformed or incomplete message history.


Summary of the issue

  • If the first message from the user is a regular prompt that leads to a text assistant message → everything works fine, even with tool calls later on.
  • If the first message triggers a tool directly → I get an error on the second interaction.

Example of the failing message sequence

[
  {
    "role": "user",
    "content": "launch the quiz"
  },
  {
    "role": "assistant",
    "content": "",
    "tool_calls": [
      {
        "id": "xyz",
        "type": "function",
        "function": {
          "name": "QuizTool",
          "arguments": "{}"
        }
      }
    ]
  },
  {
    "role": "tool",
    "content": "{...}",
    "tool_call_id": "xyz"
  }
]

There is no system message, and the assistant's first reply has content: "". When the second user message is sent (e.g. answering the quiz), the next OpenAI call fails with:

BadRequestError: 400 status code (no body)

Workaround

I added a fix to detect if the message is the first in the thread, and if so, prepend a system message:

if (isFirstMessage) {
  messages.unshift({
    role: "system",
    content: "You are a helpful assistant.",
  });
}

With this, I can use tool calls from the beginning and throughout the conversation without issues.


Questions

  • Is it expected that the message history must always start with a system or textual assistant message before any tool_call?
  • Should LangGraph enforce this or provide a helper/warning for this edge case?
  • Could the agent auto-inject a default system message if missing?

Environment

  • LangGraph: @langchain/langgraph 0.2.65
  • Node: v20.19.1
  • Model: gpt-4o-mini / mistral-small-3.1-24b-instruct-2503
  • Custom Prisma PostgresSaver used as checkpointer

Thanks a lot for your work!

Originally created by @CaillaudPA on GitHub (May 2, 2025). #### Description I'm using `createReactAgent` from `@langchain/langgraph/prebuilt` with a custom Postgres-based `checkpointSaver` for persistence. I noticed a consistent issue: when the **first user message** triggers a tool call (e.g. "launch the quiz"), the assistant returns a message with empty `content` and a `tool_calls` array. Everything looks fine at that point — the tool executes correctly, returns a `ToolMessage`, and the assistant resumes as expected. However, **on the next user message**, I get a `BadRequestError: 400 status code (no body)` from OpenAI. This happens specifically **after resuming from a checkpoint**, likely due to malformed or incomplete message history. --- #### Summary of the issue - ✅ If the *first message* from the user is a regular prompt that leads to a text `assistant` message → everything works fine, even with tool calls later on. - ❌ If the *first message* triggers a tool directly → I get an error on the *second interaction*. --- #### Example of the failing message sequence ```json [ { "role": "user", "content": "launch the quiz" }, { "role": "assistant", "content": "", "tool_calls": [ { "id": "xyz", "type": "function", "function": { "name": "QuizTool", "arguments": "{}" } } ] }, { "role": "tool", "content": "{...}", "tool_call_id": "xyz" } ] ```` There is **no system message**, and the assistant's first reply has `content: ""`. When the second user message is sent (e.g. answering the quiz), the next OpenAI call fails with: ``` BadRequestError: 400 status code (no body) ``` --- #### Workaround I added a fix to detect if the message is the first in the thread, and if so, prepend a system message: ```ts if (isFirstMessage) { messages.unshift({ role: "system", content: "You are a helpful assistant.", }); } ``` With this, I can use tool calls from the beginning and throughout the conversation without issues. --- #### Questions * Is it **expected** that the message history must always start with a `system` or textual `assistant` message before any `tool_call`? * Should LangGraph enforce this or provide a helper/warning for this edge case? * Could the agent auto-inject a default system message if missing? --- #### Environment * LangGraph: `@langchain/langgraph` 0.2.65 * Node: v20.19.1 * Model: `gpt-4o-mini` / `mistral-small-3.1-24b-instruct-2503` * Custom Prisma `PostgresSaver` used as checkpointer --- Thanks a lot for your work!
yindo added the bug label 2026-02-15 18:15:01 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#249