CopilotKit / CopilotKit/CopilotKit

🐛 Bug: NodeFetchHandler hung

Open
#6,838 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
37.4k
Forks
4.6k
Avg merge
1d 6h
Merged PRs (30d)
444

Description

♻️ Reproduction Steps
import { createControllerModule } from "@ai/apis/common/controller-module.factory";
import { V1Controller } from "@ai/apis/common/decorators";
import { jsonStringify } from "@ai/common/utils/json";
import { CopilotKitService } from "@ai/domains/copilot-kit/copilot-kit.interface";
import { CopilotKitModule } from "@ai/domains/copilot-kit/copilot-kit.module";
import {
  BuiltInAgent,
  CopilotKitIntelligence,
  CopilotRuntime,
  createCopilotRuntimeHandler,
} from "@copilotkit/runtime/v2";
import { createCopilotNodeHandler } from "@copilotkit/runtime/v2/node";
import { All, Inject, Logger, Req, Res } from "@nestjs/common";
import { ApiExcludeController } from "@nestjs/swagger";
import type { Request, Response } from "express";

@ApiExcludeController(true)
@V1Controller("/copilotkit")
export class CopilotKitController {
  private readonly logger = new Logger(CopilotKitController.name);


  @All()
  async copilotkit(

    @Req() req: Request,
    @Res() res: Response,
  ) {
    const builtInAgent = new BuiltInAgent({
      model: "openai:gpt-5.4-mini",
    });
    const runtime = new CopilotRuntime({
      agents: { default: builtInAgent }, //,
      intelligence: new CopilotKitIntelligence({
        apiKey: "fake",
      }),
      // Threads are per-user. Without this, every visitor shares one history.
      identifyUser: (request) => ({
        id: request.headers.get("x-user-id") ?? "anonymous",
        name: request.headers.get("x-user-name") ?? "Anonymous",
      }),
    });
    const handler = createCopilotNodeHandler(
      createCopilotRuntimeHandler({
        runtime,
        basePath: "/api/v1/copilotkit",
      }),
    );

    return handler(req, res);
  }
}

export const CopilotKitApiControllerModule = createControllerModule(
  CopilotKitController,
  [CopilotKitModule],
);

curl --url 'http://127.0.0.1:3333/api/v1/copilotkit' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'DNT: 1' \
  -H 'Origin: http://localhost:3000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:3000/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Chromium";v="152", "Not?A_Brand";v="24", "Brave";v="152"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{"method":"info"}'
✅ Expected Behavior

return normally

❌ Actual Behavior

/api/v1/copilotkit hung

Screenshots

No response

𝌚 CopilotKit Version
server side

npm ls | grep "@copilotkit"
├── @copilotkit/runtime@1.70.0 -> ./node_modules/.pnpm/@copilotkit+runtime@1.70.0_@cfworker+json-schema@4.1.1_@langchain+core@1.2.9_@opentelem_de5cf5235a9d6d68a70fb5c89ec0b6c1/node_modules/@copilotkit/runtime
├── @copilotkit/shared@1.70.0 -> ./node_modules/.pnpm/@copilotkit+shared@1.70.0_@ag-ui+core@0.0.59/node_modules/@copilotkit/shared


web site

 npm ls | grep "@copilotkit"
├── @copilotkit/react-core@1.56.4
├── @copilotkit/react-ui@1.56.4
├── @copilotkit/runtime@1.56.4
📄 Logs (Optional)
server side log

2026-09-02 11:21:20.964 - 01a06022-af40-7aa2-8fda-3859e0c1ff19 -  DEBUG [LoggingInterceptor] POST=>/api/v1/copilotkit | query: {} | params: {} | body: {"method":"info"}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the NodeFetchHandler path used by createCopilotNodeHandler and createCopilotRuntimeHandler in the provided NestJS controller. Reproduce the hang with the supplied curl request and compare the handler's behavior for the {"method":"info"} payload. Done means the /api/v1/copilotkit request returns normally instead of remaining open.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.