Skip to content

Read history on a thread that has never run as empty - #71

Closed
stephschofield wants to merge 1 commit into
CopilotKit:mainfrom
stephschofield:thread-history-fix
Closed

stephschofield wants to merge 1 commit into
CopilotKit:mainfrom
stephschofield:thread-history-fix

Conversation

@stephschofield

@stephschofield stephschofield commented Aug 21, 2026

Copy link
Copy Markdown

Fixes #72

What

Reading message history on a thread that has never been run returns 500 {"error":"Failed to fetch thread messages"}.

A thread id is minted before the thread exists — the platform creates it on the first run — so this is the normal opening move for every new conversation, not an error. The runtime reports the platform's THREAD_NOT_FOUND as a bare 500, which reads as a broken server and buries a stack trace in the log each time somebody opens a new chat.

Reproduced against a live Intelligence deployment:

thread state before
d3ff669d… has a prior run 200, history returned
55569917… just minted, never run 500 ← platform THREAD_NOT_FOUND

How

After a GET on /threads/:threadId/messages returns 500, ask the platform whether it lists that thread. Not listed → 200 {"messages": []}.

Only a thread the platform does not list is treated as empty. A 500 for a thread that does exist is a real failure — an outage, a bad key — and stays a 500, because answering it with empty history would tell the browser the conversation is gone and invite it to start over. Same for a failed listing, or a request with no agentId to list against.

The middleware wraps the handler rather than being added with handler.use: Hono matches middleware only against routes declared after it, and the handler arrives with all of its own already registered.

Test plan

server/src/copilot.test.ts covers the decision over a stub runtime:

  • a minted thread the platform does not list reads as empty
  • a 500 on a thread that exists stays a 500
  • a 500 stays a 500 when the listing itself fails
  • a 500 stays a 500 with no agentId to list against

Verified against a live deployment: minted thread → {"messages":[]}, existing thread → 200 with history intact. typecheck and biome check clean.

A thread id is minted before the thread exists — the platform creates it on
the first run — so reading history on a conversation nobody has spoken in yet
is the normal opening move. The runtime reports the platform's
THREAD_NOT_FOUND as a bare 500, which reads as a broken server and buries a
stack trace in the log every time somebody opens a new chat.

Only a thread the platform does not list is treated as empty. A 500 for a
thread that does exist is a real failure and stays a 500: answering it with
empty history would tell the browser the conversation is gone and invite it to
start over.

Wrapped rather than added with handler.use, because Hono matches middleware
only against routes declared after it and the handler arrives with its own
already registered.
@davidmckayv

Copy link
Copy Markdown
Contributor

Closing this. The diagnosis is right — a brand-new thread spams a fake 500, and that's worth fixing — but the mechanism has two problems. It guesses by listing the user's threads and rewriting the 500 to empty when the thread is absent, and that list is paginated and excludes archived threads, so a power user whose thread is past page one, or anyone with an archived thread, gets a genuine history-store outage reported as "this conversation has no messages" — the silent failure the PR's own comment says must not happen. Separately, merging it silently reverts the telemetryProperties: { accessibility_title } block on copilot.ts with no conflict to warn anyone, and the tests re-implement the middleware inline so they pass with the real code deleted. The correct fix is small and sitting unused: PlatformRequestError carries .status, so branch on error.status === 404 for an exact answer in one call. Send that and it's a quick merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reading history on a thread that has never run returns 500

2 participants