openai / openai/codex

[Windows Desktop] Scheduled stop on active goal creates thousands of empty turns and hides transcript history

Open
#45,026 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app automations bug rate-limits session windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of the Codex App are you using?
  • Codex Desktop AppX: 26.908.4834.0 (x64)
  • Bundled/available Codex CLI: 0.154.0
What subscription do you have?

Paid ChatGPT account. The incident crossed an account usage-limit boundary.

What platform is your computer?
  • Windows 11 Pro x64
  • OS build 26200
  • Local Codex project/thread
What issue are you seeing?

A long-running goal worked normally until a one-time scheduled stop message was delivered to the same thread around the time the account reached its usage limit. The goal remained active after the stop message, and Codex generated thousands of synthetic goal-continuation turns, most with empty final_answer messages. The Desktop transcript then stopped rendering the real conversation history and showed a mostly blank viewport.

The stored history was not deleted. The app-server can still page through it, but the newest pages contain empty turns, and the Desktop UI does not progress to usable older messages.

This appears to combine three failure modes:

  1. A scheduled stop message can race with an active goal without actually pausing the goal.
  2. Goal continuation can enter a tight loop that emits empty completed turns, including across a usage-limit event.
  3. Transcript pagination/rendering does not skip empty turns or continue fetching until visible messages are available.
Observed sequence

All timestamps below are UTC.

  1. The long-running goal had operated normally for several days and was paused on 2026-09-05T18:30:25Z.
  2. The same goal was reactivated on 2026-09-12T01:56:50Z.
  3. A one-time thread heartbeat was scheduled for 2026-09-12T02:30:00Z (10:30 PM America/New_York). Its prompt told the task to stop new experiments, finish only necessary recovery, save a checkpoint, and stop. It also warned that the goal might need the app's Pause control.
  4. The scheduled stop message appeared in the thread. The goal itself remained active.
  5. The first empty assistant final_answer was recorded at 2026-09-12T02:32:23.137Z, shortly after the scheduled stop.
  6. Usage-limit failures were recorded at 2026-09-12T06:52:49.074Z and 2026-09-12T06:53:25.866Z.
  7. Empty completed turns continued until 2026-09-12T12:13:10.784Z.
  8. The goal was finally changed from active to paused at 2026-09-12T12:13:09.042Z.
  9. Opening the thread in Desktop showed the scheduled message near the bottom and a large blank transcript area. Older messages could not be reached normally.
Quantified local evidence

Sanitized counts from the local rollout JSONL:

  • Rollout size: 248,019,503 bytes (236.53 MiB)
  • turn_context records: 4,295
  • Internal goal-continuation prompts: 4,268
  • Assistant final_answer messages: 4,273
  • Empty assistant final_answer messages: 3,769
  • Non-empty assistant final_answer messages: 504
  • Empty turns were often created every 2–5 seconds.

A read-only thread/turns/list check returned:

  • the thread itself as idle after the goal was paused;
  • hasMore: true, proving older pages still exist;
  • newest pages containing completed turns with items: [] or assistant messages whose text is empty.

The visible failure is therefore not message deletion. It is a goal/state runaway that produced a pathological history, followed by a Desktop pagination/rendering failure over that history.

I am intentionally omitting the full thread ID, local project paths, raw transcript, and tool output because they contain private operational details. I can provide a redacted event sample or the full session through a maintainer-approved private channel.

Steps to reproduce
  1. Start a long-running goal in a local Codex Desktop thread.
  2. Let it run long enough to approach an account usage limit.
  3. While the goal is active, add a one-time thread heartbeat whose message instructs the task to stop at a specified time but does not mark the unfinished goal complete or blocked.
  4. Let the scheduled stop message arrive while the goal runner is active.
  5. Allow the account usage limit to be reached before the goal is explicitly paused in the UI.
  6. Inspect the rollout JSONL for repeated internal goal-continuation prompts and empty assistant final_answer records.
  7. Reopen the thread and try to scroll through all messages.
Expected behavior
  • Reaching a usage limit should transition the goal once into a non-running state without repeated continuation attempts.
  • A scheduled stop instruction delivered to an active goal should not leave the goal runner generating synthetic continuation turns indefinitely.
  • A completed model turn should not be persisted as an empty final_answer unless it has meaningful visible content or error state.
  • Desktop history loading should skip empty synthetic turns and keep paging until visible messages are found.
  • The complete stored conversation should remain reachable even when a thread contains many turns.
Actual behavior
  • The goal stayed active after the stop message.
  • Thousands of automatic continuation turns were created.
  • Most assistant finals were empty.
  • The rollout grew to 236.53 MiB.
  • Desktop rendered a mostly blank transcript and did not expose the older stored messages.
Related issues
  • #23828 — /goal loops after usage limit and repeatedly triggers compaction (closed; this looks like a regression/variant)
  • #31995 — long conversations show only recent turns although full rollout history remains local
  • #25779 — meta issue for unbounded session/turn state and lost active-turn control

This report adds the scheduled-stop interaction, a current Windows reproduction, exact lifecycle timestamps, and verified empty-turn counts.

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 by reproducing the scheduled-stop and usage-limit sequence, then inspect the rollout JSONL and the thread/turns/list results described in the report. Trace the goal state transition, continuation records, and Desktop history loading; done means the goal stops once, empty turns do not accumulate, and older visible messages remain reachable.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.