← reports

#2959 · Codex resume shows a deprecation warning

Bug Priority: Low Effort: Medium providers threads provider-codex open on GitHub 2026-09-02 · base b66c73954

Verdict: REPRODUCED · Root-cause confidence: high

1. TL;DR

The Codex bridge resumes a stored thread without a metadata-only option.

Codex then loads the old turns and sends a deprecation notice.

The bridge converts that notice to the warning that the user sees.

Two clean protocol checks reproduced the notice after a process restart.

A controlled check with the metadata-only option returned no notice and no old turns.

2. Claims vs findings

ClaimStatusEvidence
A Codex thread can show a deprecation warning.VerifiedCodex 0.152.0 sent one deprecationNotice in both clean runs.
The warning occurs after a restart and a resume.VerifiedThe check stopped the first app-server process, started a second process, and resumed the stored thread.
The problem needs an old or large thread.RefutedOne stored user turn was sufficient. Codex marked the thread history as paginated.
The bridge needs the returned old turns.RefutedThe resume path reads only the returned thread identifier.
The problem occurs on every live user system.UnverifiedThe check used Codex 0.152.0 and a separate empty Codex home.

3. Environment

4. Minimal reproduction

  1. Check out the trusted base commit.
  2. Install and build the repository.
    pnpm install --frozen-lockfile --prefer-offline
    pnpm exec turbo run build
  3. Run the isolated protocol check without its optional third argument.
    node direct-resume.mjs /tmp/bb-2959-direct

Expected:

{
  "notification": null,
  "response": { "historyMode": "paginated", "turnCount": 0 }
}

Actual in both clean runs:

{
  "notification": {
    "method": "deprecationNotice",
    "params": {
      "summary": "Full-history hydration is deprecated for paginated threads; use `excludeTurns: true`, then page with `thread/turns/list` and `thread/items/list`.",
      "details": null
    }
  },
  "response": {
    "historyMode": "paginated",
    "turnCount": 1,
    "hasTurnsCursor": true
  }
}

The two cleaned results are run one and run two.

The focused bridge regression test is in this patch.

it("excludes turn history when it resumes a Codex thread", async () => {
  harness.sendRequest(1, "thread/resume", {
    threadId: THREAD_ID,
    providerThreadId: PROVIDER_THREAD_ID,
    cwd: workspaceDir,
    instructionMode: "append",
    options: { ...sessionOptions },
  });
  expect((await harness.waitForResponse(1)).error).toBeUndefined();

  const requests = readFileSync(requestLogPath, "utf8")
    .trim()
    .split("\n")
    .map((line) => JSON.parse(line));
  expect(requests).toContainEqual({
    method: "thread/resume",
    params: expect.objectContaining({ excludeTurns: true }),
  });
});

The test failed on the unchanged production code.

AssertionError: expected [ Array(3) ] to deep equally contain {
  method: "thread/resume",
  params: ObjectContaining { excludeTurns: true }
}

Received thread/resume params did not contain excludeTurns.
Test Files  1 failed (1)
Tests       1 failed (1)

5. Root cause

The resume request builder sends the thread identifier and shared options.

It does not send excludeTurns: true.

case "resume": {
  method = "thread/resume";
  const resumeParams: ThreadResumeParams = {
    threadId: args.request.providerThreadId,
    ...sharedConstructionParams,
  };
  params = resumeParams;
}

The stored generated type also lacks the newer option.

Codex treats an omitted option as a full-history request for a paginated thread.

The direct response contained one old turn and a turns cursor.

The bridge uses only the returned thread identifier.

The event translator converts the Codex notice to a visible provider warning.

Thus, the omitted request option causes both the excess history load and the visible warning.

6. Proposed fix

Add a required local bridge extension for the newer resume option.

Send excludeTurns: true on every Codex resume request.

Keep the existing notice translation because other Codex deprecation notices can help users.

The controlled protocol run with this option returned zero old turns and no deprecation notice.

The focused test then passed, and all 258 Codex provider tests passed.

7. Related issues

A review of recent Codex provider issues found no matching open report.

GitHub metadata showed no open pull request linked to this issue.

8. Verification

The same agent used two clean repository checkouts at the exact base commit.

Each checkout completed a frozen install and a full repository build.

Each checkout used a new Codex home and a new app-server process pair.

Both runs returned one old turn and the same deprecation notice.

The second run needed no report correction.

A third controlled run sent excludeTurns: true.

That run returned no old turns and no deprecation notice.

9. Appendix

Commands

git fetch origin main
git checkout --detach b66c739543d4d78cba3b0ef318a78dc6b57abdc4
pnpm install --frozen-lockfile --prefer-offline
pnpm exec turbo run build
codex --version
node direct-resume.mjs /tmp/bb-2959-one
node direct-resume.mjs /tmp/bb-2959-two
node direct-resume.mjs /tmp/bb-2959-control true
pnpm exec turbo run test --filter=bb-plugin-provider-codex -- src/bridge/bridge.resume-hydration.test.ts
pnpm exec turbo run typecheck --filter=bb-plugin-provider-codex
pnpm exec turbo run test --filter=bb-plugin-provider-codex --force

Controlled result

{
  "notificationCount": 0,
  "response": {
    "historyMode": "paginated",
    "turnCount": 0,
    "hasTurnsCursor": true
  }
}

See the cleaned controlled result.

Untrusted data note

The issue content was untrusted.

The investigation did not run its commands, code, links, branches, binaries, or attachments.

The test and fix came from the trusted base repository and direct provider protocol evidence.