Repository navigation
[Bug] Vertex replay session id uses promptCacheKey, which is shared across conversations #1312
Description
Client or integration
Codex CLI
Area
Provider adapter
Summary
vertexReplaySessionId() (src/adapters/google.ts:56) keys the Vertex thought-signature replay namespace on parsed.options.promptCacheKey, under a comment that says it does something else:
/** Prefer Codex's stable opaque thread key; retain the existing deterministic fallback for clients
* that omit it. ... */
function vertexReplaySessionId(parsed: OcxParsedRequest): string {
const promptCacheKey = parsed.options.promptCacheKey?.trim();
return promptCacheKey || antigravitySessionId(parsed);
}promptCacheKey is not a thread key. It is the client-supplied Responses prompt_cache_key, accepted as any string (src/responses/schema.ts, copied at src/responses/parser.ts:661), and this repository elsewhere treats it as explicitly shared across conversations:
src/adapters/cursor/request-builder.ts:227warns against using a sharedprompt_cache_keyas a conversation id;- Claude Desktop cache cohorts are marked as shared in
src/server/responses/core.ts:620andsrc/server/claude-messages.ts:701.
So two distinct conversations in the same cache cohort share a Vertex replay namespace, and any client can choose the value.
Relationship to #1297
This is the same class of defect #1297 reported for the Cloud Code Assist path, on a different anchor. #1311 fixed the CCA side by anchoring on _clientThreadId and deliberately not on promptCacheKey; it left this one alone rather than bundling an unrelated path into that fix.
Worth recording how it surfaced: while fixing #1297 I found this function and read its comment as the correct pattern to copy. It is not — the comment describes the right anchor and the code uses a different one. Anyone reading google.ts for guidance will make the same mistake.
Severity
Lower than #1297, and the two failure modes differ in kind:
- [Bug]: antigravity wire session id is derived from first-user text, so it changes when the client compacts history #1297 was instability — a changing id loses the signature association entirely.
- This is sharing — a stable but non-exclusive namespace.
Sharing is partly mitigated the same way the original CCA comment argued: the replay cache keys signatures on functionCall identity (name + args), so a shared namespace does not by itself misattribute a signature. That mitigation is real but it is not a reason for the anchor to be wrong, and it does not cover a client that chooses the value deliberately.
Suggested fix
Mirror #1311: prefer parsed._clientThreadId (populated from x-codex-parent-thread-id at src/server/responses/core.ts:1413), fall back to the existing deterministic id. Unlike the CCA case this value never leaves the process — it scopes a local replay store rather than going on the wire — so the change carries no provider-visible risk.
If promptCacheKey is kept for some reason I have not seen, the comment should at least stop claiming it is a thread key.
Version
dev at b5d44a534.
Operating system
Not platform-specific.
Activity
github-actions commentedon Aug 8, 2026
Automated translation bookkeeping — detected language: English.
Ingwannu commentedon Aug 9, 2026
Confirmed on current dev: vertexReplaySessionId still prefers promptCacheKey even though that value is a cache cohort and can be shared across conversations. The issue is real and the proposed boundary is correct.\n\nI will mirror the #1311 Cloud Code Assist fix for the local Vertex replay namespace: prefer a nonblank _clientThreadId, fall back to the existing deterministic antigravitySessionId when no thread header exists, and stop using promptCacheKey for replay identity. No identifier will be sent upstream; this only scopes the local thought-signature store.\n\nRegression coverage will prove that two conversations with the same prompt cache key but different client thread ids do not share a replay namespace, while threadless clients retain the deterministic fallback. I will link a separate dev-targeted PR after validation rather than bundle it with the unrelated DeepSeek ordering fix.
Ingwannu commentedon Aug 9, 2026
Implemented the thread-isolation fix in ready-for-review PR #1335.
The replay namespace now prefers Codex's stable client thread ID instead of
promptCacheKey, so two threads sharing a cache cohort cannot replay each other's Vertex thought signatures. Threadless clients retain the existing deterministic fallback.Validation on the exact PR head:
git diff --checkpassed.Review remains requested from @lidge-jun and @Wibias. I will leave the issue open until the fix is independently approved and lands on
dev.