Skip to content

Goal ignores an explicit human-hours pause and burns 1.26M tokens in 12 no-op turns #41831

Open

Description

@Kizuno18

What version of Codex are you using?

Codex Desktop with connected codex-cli 0.150.1 runtime.

Model: gpt-5.6-sol, xhigh reasoning.

What platform are you using?

Nobara Linux 44, x86_64, kernel 7.2.0-202.nobara.fc44.x86_64.

When did this happen?

2026-08-31 in America/Sao_Paulo (UTC-03:00).

  • Session started: 08:29:14 local / 11:29:14 UTC
  • Goal created: 08:35:31 local / 11:35:31 UTC
  • Main work turn completed: 09:08:50 local / 12:08:50 UTC
  • Repeated continuation window: 09:08:50–09:10:33 local / 12:08:50–12:10:33 UTC
  • Goal status finally changed to paused: 09:10:28 local / 12:10:28 UTC

What happened?

I gave Codex a 737-line execution handoff for a private, multi-day implementation. The project context is intentionally anonymized, but the relevant handoff structure was:

  • eight ordered phases (0–7), with Phase 0 explicitly read-only;
  • research, correctness, compatibility, build, QA, worklog, and publication gates;
  • a resume capsule, evidence ledger, and worklog for cross-session state;
  • a maximum of 8 human-equivalent work hours per Monday–Friday day and 40 hours per week;
  • closeout counted inside the 8-hour cap, weekends with zero planned capacity, and unfinished work deferred to the next weekday;
  • an explicit requirement to stop working and pause when the human-equivalent capacity limit was reached;
  • remote publication prohibited until a late final-phase gate.

During the first work turn, I sent this additional instruction:

Set a Goal whose objective is completing this implementation, and always pause it when the human-time limit is exceeded.

Codex created an active Goal whose objective included completing all phases and gates while performing closeout and stopping at the 8-hour/40-hour human-equivalent limits.

When its worklog reached 8/8 human-equivalent hours for the day, Codex performed closeout and ended the main turn with a clear terminal response saying execution was paused until the next real weekday. The implementation was incomplete, so the Goal correctly was not marked complete. It also was not blocked.

However, the persisted Goal was still active. Only 79 ms after the main task_complete, the Goal continuation hook started a new turn and injected:

<codex_internal_context source="goal">
Continue working toward the active thread goal.
...
Tokens remaining: unbounded
...
Do not call update_goal unless the goal is complete or the strict blocked audit above is satisfied.
</codex_internal_context>

The assistant honored the handoff and responded that no work could occur because the 8/8-hour human-equivalent limit had been reached. As soon as each no-op turn completed, the hook immediately started another one. This repeated 12 times without user input or project work.

The loop stopped only after the persisted Goal status changed to paused. The rollout does not show an agent tool call that caused that status transition.

Sanitized event sequence

09:08:50.589 task_complete  # main work turn and daily closeout
09:08:50.668 task_started   # automatic continuation, +79 ms
09:08:51.263 internal goal continuation injected
09:09:01.955 assistant: goal remains active, execution paused until next weekday
09:09:02.071 task_complete
09:09:02.108 task_started   # automatic continuation again, +37 ms
...
09:10:26.791 task_started   # 12th automatic continuation
09:10:27.373 internal goal continuation injected
09:10:28.168 thread_goal_updated status=paused
09:10:33.395 task_complete

Total repeated-continuation duration: about 1 minute 43 seconds.

Token impact

These are recorded runtime counters, not a billing estimate:

Counter Before loop After loop Increase
total_token_usage.total_tokens 10,485,436 11,751,024 1,265,588
Input tokens 10,447,054 11,711,643 1,264,589
Cached input tokens 9,998,080 11,240,704 1,242,624
Output tokens 38,382 39,381 999
Goal tokensUsed 384,976 406,034 21,058

Each automatic no-op turn recorded roughly 98,772–112,114 total tokens because the same large context was reprocessed. Most were cached input, but the rollout's total token counter still increased by 1.26M and the Goal counter also increased.

Why the Goal contract could not honor the request

The agent-facing Goal lifecycle creates an active Goal, while the available update_goal operation only permits complete or blocked. It does not expose paused, waiting, or a wake time. The injected continuation context also explicitly forbids using blocked for an ordinary pause.

That leaves no valid agent action for this requested state:

Goal incomplete
+ daily human-equivalent capacity exhausted
+ preserve Goal for the next weekday
+ perform no more model turns until then

The assistant can say it is paused, but the scheduler still sees an active Goal and immediately requeues it.

Expected behavior

  • An explicit pause/stop condition inside the Goal objective must be able to persist a non-continuing state.
  • The agent should be able to set paused or waiting, ideally with an optional wakeAt timestamp.
  • The scheduler should re-check Goal state before enqueueing and before injecting a continuation.
  • Queued or in-flight continuation leases should be discarded after a pause.
  • Repeated semantically identical no-progress responses should trigger deduplication, backoff, and a low continuation/usage circuit breaker.
  • A time-based wait should not require misclassifying a healthy Goal as blocked.
  • The UI should expose that execution is paused while preserving the incomplete Goal.

Related issues

The full rollout contains private workspace details and is not suitable for public attachment. I can provide targeted sanitized event excerpts privately if needed.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    on Aug 31, 2026
  2. github-actions commented on Aug 31, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  3. Kizuno18 commented on Sep 1, 2026

    @Kizuno18
    Author

    Follow-up: reproduced again the next day in the same private thread

    This happened again on 2026-09-01 in America/Sao_Paulo (UTC-03:00), with a much larger impact.

    The user explicitly resumed the next day's work at 07:18:32 local. The persisted Goal became active at 07:37:35. A legitimate work turn then ran and completed its first-phase closeout at 08:30:41.925 local. Its terminal response explicitly said the daily 8/8 human-equivalent hours had been reached, execution was paused until the next weekday, and the incomplete Goal would remain available for the following phase.

    The continuation scheduler started another turn 181 ms later, despite that terminal condition. No human input occurred during the resulting loop.

    Second-loop timeline

    2026-09-01 08:30:41.925 UTC-03  task_complete  # legitimate work + daily closeout
    2026-09-01 08:30:42.106 UTC-03  task_started   # automatic Goal continuation, +181 ms
    2026-09-01 08:30:43.020 UTC-03  internal Goal context injected
    ...
    2026-09-01 10:23:03.180 UTC-03  task_complete  # last completed no-op response
    2026-09-01 10:23:03.241 UTC-03  task_started   # another automatic continuation
    2026-09-01 10:23:03.368 UTC-03  internal Goal context injected
    2026-09-01 10:23:03.787 UTC-03  rate limit at 100%
    2026-09-01 10:23:03.898 UTC-03  task_complete with no assistant response
    

    Equivalent UTC window: 11:30:41.925–13:23:03.898 UTC.

    Observed duration: 1h 52m 21.792s.

    Loop shape

    • 1,621 automatically started Goal-continuation turns
    • 1,621 injected <codex_internal_context source="goal">Continue working toward the active thread goal...</codex_internal_context> messages
    • 1,620 no-progress final replies
    • 1,594 replies were exactly pausado até o próximo dia útil after trimming whitespace
    • Only one tool call occurred in the entire loop; it merely enumerated available Goal/pause tools
    • The other 1,620 turns performed no tool call and no project work
    • Completion-to-next-start gap: 57 ms median, 131 ms p90, 654 ms maximum
    • All 1,621 requeues occurred in less than 1 second; there was no backoff or duplicate-output circuit breaker

    The loop stopped only because the provider rate limit reached 100%. The durable Goal row then became usage_limited, not paused.

    Token-counter impact

    These are source-scoped cumulative runtime counters from one monotonic epoch, not a billing total or cost estimate:

    Counter Before loop After loop Observed increase
    total_token_usage.total_tokens 32,323,160 254,721,570 222,398,410
    Input tokens 32,231,698 254,607,645 222,375,947
    Cached input tokens 31,829,888 251,211,648 219,381,760
    Output tokens 91,462 113,925 22,463
    Reasoning output tokens 26,652 28,619 1,967

    The Goal's own tokensUsed value embedded in continuation contexts rose from 899,306 on the first no-op continuation to 3,915,956 on the final one: an increase of 3,016,650.

    Per-turn last_token_usage.total_tokens also grew from 54,868 on the first automatic no-op turn to 200,205 on the final completed one. This shows a context-amplification loop: every duplicate turn enlarged the history that the next duplicate turn processed.

    Direct tool-contract evidence

    On the fourth automatic continuation, the assistant inspected every available tool whose name or description matched goal|pause.

    The only relevant controls were:

    • create_goal
    • get_goal
    • update_goal

    The exposed update_goal schema allowed only:

    status: "complete" | "blocked"
    

    Its description explicitly said:

    You cannot use this tool to pause, resume, budget-limit, or usage-limit a goal;
    those status changes are controlled by the user or system.
    

    The Goal was incomplete and not genuinely blocked, so the agent had no valid state transition that could honor the Goal's explicit daily pause condition. Saying “paused” in the final answer had no scheduler effect.

    This second reproduction makes the missing safety boundary clearer: a no-progress Goal can continue at sub-second cadence until quota exhaustion, while its ever-growing history makes each duplicate turn progressively more expensive.

    Suggested regression test:

    1. Run an incomplete Goal with an explicit terminal wait condition
    2. Let the condition become true
    3. Return the same no-progress terminal response twice
    4. Verify the Goal enters a durable non-continuing state before a third model turn
    5. Verify no queued continuation can publish after that state change
    6. Verify rate-limit exhaustion is not the mechanism that stops the loop
  4. cyberianin commented on Oct 7, 2026

    @cyberianin

    Environment: Windows 10 LTSC 21H2, Codex App 26.1002.6548.0 (OpenAI.Codex_26.1002.6548.0_x64__2p2nqsd0c76g0).

    Reproduced on October 7, 2026 with an active long-running Goal.

    I can still reproduce this class of failure with an explicit deferred pause instruction in an active long-running Goal.

    The important difference from an immediate “pause now” request is that I asked Codex to finish one bounded piece of work, produce its report, and then stop before returning to the larger Goal.

    My instruction was effectively:

    Accept this batch and create a separate commit for it. Do not push.

    After the commit, show the requested Git status/log/show output and provide the batch report.

    After the commit, do not automatically proceed to fixing the Windows concurrency issue.

    Stop first with the report and the exact commit SHA.

    Codex completed the requested batch and replied with the commit SHA and report. Its response explicitly said:

    Push was not performed.

    .codex/ and .temp/ were not included in the commit.

    I did not proceed to the Windows concurrency issue.

    At that point the requested stopping condition had been reached exactly.

    However, the Goal remained active. After the turn completed, an automatic Goal continuation started and Codex immediately resumed work on the larger objective:

    I’ll reconcile the goal and the new HEAD. For the startup baseline I’ll try to run the MCP server directly in an exec session...

    It then started running additional commands and measurements without any new user instruction.

    So in this reproduction, the model appears to have understood the user-level instruction correctly: it completed the bounded batch, produced the requested report, and explicitly acknowledged that it would not proceed further. The failure appears at the Goal lifecycle boundary: completing that turn did not transition the persisted Goal out of active, so the automatic continuation scheduler resumed the larger objective.

    This is particularly problematic for long-running Goals composed of multiple stages. A user needs to be able to say “finish this subtask, checkpoint/report, then stop” without having to expose or know an internal lifecycle API such as update_goal(status="paused").

    Expected behavior: an explicit deferred stop/pause condition in a user message should become a Goal lifecycle boundary. Once the requested bounded work and report are complete, the Goal should enter paused and no autonomous continuation should be scheduled until the user explicitly resumes it.

    This looks closely related to #46904, but that report covers an immediate natural-language pause. This reproduction covers a deferred pause after a finite subtask/checkpoint, which is an important workflow for multi-stage Goals.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions