makecindy / makecindy/cindy

Codex pre-sampling compaction fails when custom_tool_call history uses fc_ IDs

Open
#4,112 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2.7k
Forks
401
Avg merge
21h 48m
Merged PRs (30d)
776

Description

## Summary

A long-running Codex session becomes permanently unusable when pre-sampling compaction replays a persisted `custom_tool_call` whose item ID starts with `fc_` instead of `ctc_`.

The live thread works for many turns, but once automatic compaction is triggered, the upstream Responses endpoint rejects the replayed history with HTTP 400.

## Environment

- Cindy: `0.1.74`
- Codex CLI: `0.153.4`
- Model/provider: `gpt-5.6` via `cindy_gateway`
- Platform: macOS arm64
- Observed: 2026-09-08

## Error

```text
Invalid 'input[5].id': 'fc_0d4928f51d034f5e016a9fb59ad1ec87d0ac326c5ecf5a8e36'. Expected an ID that begins with 'ctc'.
```

The app-server logs the terminal failure as:

```text
ERROR codex_core::session::turn: Failed to run pre-sampling compact
```

## Evidence

The persisted rollout item is:

```json
{
"type": "custom_tool_call",
"id": "fc_0d4928f51d034f5e016a9fb59ad1ec87d0ac326c5ecf5a8e36",
"status": "completed",
"call_id": "call_Vtr7eYLfTJKQ6JaXLpgDJaJl",
"name": "exec"
}
```

In the affected rollout, all 97 persisted `custom_tool_call` items use an `fc_` ID; none use `ctc_`.

Immediately before the failure, the latest turn used about `207288 / 258400` context tokens. The next turn triggered pre-sampling compaction, which replayed the malformed historical item and failed deterministically. Retrying the same turn produces the same 400.

## Steps to reproduce

1. Start a Codex session using `gpt-5.6` through `cindy_gateway`.
2. Execute custom tools such as `exec` over enough turns to create a long history.
3. Confirm the persisted response items are `custom_tool_call` objects with `fc_` IDs.
4. Continue until Codex triggers pre-sampling compaction, or resume/replay the thread in a way that resubmits history.
5. Observe the upstream 400 requiring an ID beginning with `ctc`.

## Expected behavior

Cindy/Codex should be able to compact or resume the thread without invalidating persisted tool history.

## Suggested fix

Normalize Responses history at the provider/replay boundary:

- Ensure newly persisted `custom_tool_call` item IDs use the correct `ctc_` form.
- Before compaction/resume replay, sanitize legacy `custom_tool_call` IDs that use `fc_`, while preserving `call_id` so tool calls remain paired with `custom_tool_call_output`.
- Add a regression test covering pre-sampling compaction with legacy malformed IDs.

The available logs establish the malformed persisted type/ID pair and the compaction trigger. They do not establish whether LiteLLM originally emitted the wrong item ID or Codex converted the item type while retaining an `fc_` ID.

Contributor guide

Open the contributing guide

Research direction

Start at the provider/replay boundary and the pre-sampling compaction path, then inspect how persisted custom_tool_call IDs and call_id values are replayed. Add a regression test for pre-sampling compaction with legacy fc_ IDs, preserving pairing with custom_tool_call_output. Done means compaction or resume no longer produces the upstream invalid-ID error.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
ai, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.