[Bug]: t3_thread_read drops the typed failure (usage_limit class and resetAt) on error items

Open Beginner friendly
#35,270 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript

Research direction

Start with the MCP contracts in packages/contracts/src/orchestratorMcp.ts and the timelineItem() and thread detail builder in apps/server/src/mcp/OrchestratorMcpService.ts. Trace how the error item and thread shell fields are mapped into the response, then check existing MCP contract and service tests. Done when t3_thread_read exposes the typed failure class and reset time for error items and thread details.

Written by the indexing model from the issue text.

Description

Before submitting
  • I searched existing issues and did not find a duplicate. (#31057 is about limited children resuming on the wrong account; it is not this.)
  • I included enough detail to reproduce or investigate the problem.
Area

apps/server: the orchestrator MCP read (t3_thread_read)

Steps to reproduce
  1. Start a thread on a provider that is out of usage. Seen with Codex, which fails the turn with usageLimitExceeded.
  2. The turn fails. T3's own store holds the typed failure on the error item: in orchestration_v2_projection_turn_items, failure = { class: "usage_limit", code: "usageLimitExceeded", resetAt: "<ISO>" }. The thread shell's lastErrorClass and usageLimitResetAt are set from it (threadErrorSummary).
  3. Read the thread through MCP: t3_thread_read with view: "activity", and the default view.
Expected behavior

An MCP client can tell a usage-limit failure, and its reset time, from any other failure using typed fields, without reading the human-readable message. One of these:

  • OrchestratorMcpThreadTimelineItem for type: "error" carries failure: { class, code, resetAt }, or at least failureClass and resetAt;
  • the thread object returned by t3_thread_read carries lastErrorClass and usageLimitResetAt, as the shell projection already does.
Actual behavior

The error item comes back with type, status, title, text and ids only. failure reaches the client only as text, because turnItemText returns item.failure.message for case "error" (apps/server/src/mcp/OrchestratorMcpService.ts, timelineItem(), at ac781dcb). The thread object has no lastErrorClass or usageLimitResetAt.

Claude limits are visible, because they also produce a system_notice whose item id ends usage-limit:…:<window>:<reset epoch seconds>. Codex limits produce only the error item, so through MCP a Codex usage limit looks like any other failed turn.

Impact

An MCP client that orchestrates agents cannot treat a usage limit as a wait without parsing English error text. It sees a plain failure, and may fail or relaunch work that T3's own UsageLimitRecoveryWorker would resume at resetAt. The fix is small: add the typed fields to the MCP timeline item and thread contracts in packages/contracts/src/orchestratorMcp.ts, then fill them in timelineItem() and the thread detail builder.

Version or commit

main at 59118847; OrchestratorMcpService.ts last changed in ac781dcb.

Environment

T3 server on Linux, threads started over MCP.

Logs or stack traces

The error item's text on the Codex thread: "You've hit your usage limit. Visit https://chatgpt.com/settings/usage to purchase more credits or try again at Nov 17th, 2026 7:32 PM."

— Model: claude-opus-5-5 · Harness: Claude Code (T3 Code)

Dominant language
TypeScript
Stars
24.8k
Forks
6.4k
Avg merge
4h 16m
Merged PRs (30d)
352

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

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.

More from pingdotgg/t3code

All issues in pingdotgg/t3code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.