#Got claude api error using headless ui with frontend tools - tool_use found without tool_result

1 messages · Page 1 of 1 (latest)

oblique ridge
#

Error:
Claude API error (status 400): Error code: 400 - {'message': 'messages.10: tool_use ids were
found without tool_result blocks immediately after: toolu_bdrk_01Qw1gmGJJb4o97UrVVadfw6.
Each tool_use block must have a corresponding tool_result block in the next message.'}

grim echoBOT
#

This solution has been AI generated

You're seeing this because Claude emitted a tool_use, but your app didn’t send a matching tool_result in the very next message. With Headless UI + frontend tools, make sure every frontend tool execution produces a returned value so CopilotKit can emit the required tool_result.

Why this happens

  • Anthropic requires each tool_use to be immediately followed by a tool_result.
  • If a frontend tool handler is missing or doesn’t return a value, no tool_result is sent, causing the 400 error.

How to fix

  • Define your tools with useFrontendTool and ensure the handler returns a value. That return becomes the tool_result.
import { useFrontendTool } from "@copilotkit/react-core";

useFrontendTool({
  name: "updateUserProfile",
  description: "Updates the user's profile information",
  parameters: {
    name: { type: "string" },
    email: { type: "string" }
  },
  handler: async ({ name, email }) => {
    const result = await updateProfile(name, email);
    return {
      success: true,
      message: `Profile updated for ${name}`,
      data: result,
    }; // <- generates the tool_result
  },
  render: ({ name, email }) => <div>Updating profile for {name}...</div>,
});

Common mistakes (cause this error)

// Missing handler – no tool_result emitted
useFrontendTool({ name: "myTool", parameters: { v: { type: "string" } }, render: () => <div/> });

// Handler without return – no tool_result emitted
useFrontendTool({
  name: "myTool",
  parameters: { v: { type: "string" } },
  handler: async ({ v }) => { doSomething(v); /* no return */ },
});
#

Alternatives for UI-only or interactive flows

  • Render-only tools: useRenderToolCall
useRenderToolCall({ name: "displayChart", handler: ({ data }) => <Chart data={data} /> });
  • Interactive approval: useHumanInTheLoop (returns a value -> tool_result)
useHumanInTheLoop({ name: "approveAction", handler: async ({ action }) => ({ approved: await waitForUserApproval(action) }) });

Key points

  • Every tool_use must be followed by a tool_result.
  • Always provide a handler and return a value in useFrontendTool.
  • Use render/interactive hooks appropriately when no execution result is needed.

Was this helpful?

If this solution worked for you, please click on the appropriate option below to help us improve:

grim echoBOT
#

Thank you for your feedback! Our team will provide additional assistance. 🔄

#

Hi @oblique ridge, does this answer your question?

oblique ridge
#

@misty moat Unfortunatly no..

#

i come with different solution of filtering the messages sent to agent on the BE side. I would aprreciate to got some feedback if that's the right approach

oblique ridge
#

@misty moat Will appreciate your help here