Interactions API: previous_interaction_id chain re-roots mid-conversation, then rejects a valid function_result
Model: gemini-3.8-flash · Endpoint: POST /v1beta/interactions (streaming) · SDK: google-genai 2.8.0 and 2.25.0 (same result) · Reproduced: 2026-09-22
Summary
In a tool-calling conversation chained only with previous_interaction_id, the server
sometimes starts a new conversation root partway through. Two interactions later,
answering the pending function_call with a function_result fails with:
invalid_request: Please ensure that function response turn comes immediately after a function call turn. Got function response with name 'run_travel_code'.
The client's request is valid. The interaction being chained off ends in a function_call,
and the function_result answers that call's id.
How the re-root shows up
An interaction id is v1_<urlsafe base64 protobuf>: field 1 is the conversation root id and
field 2 is the interaction's own id. They should be equal only on a conversation's first
interaction. In failing runs they become equal mid-chain (RE-ROOTED below). The
rejection follows two interactions later, when the rebuilt history seems to start with a
function_result whose function_call belongs to the old root.
Evidence it is server-side
Checked against the rejected interaction:
- Its stored steps are function_result -> thought -> function_call, so answering it is legal.
- Replaying the identical request is rejected every time; it isn't transient.
- Plain-text input chained to the same interaction is accepted.
- The same history flattened from interactions.get and sent explicitly, without
previous_interaction_id, is accepted. Same content, so only the server-side chain
reconstruction is wrong.
Not caused by the SDK: reproduces on 2.8.0 and 2.25.0, and toggling the api-revision
header 2.8.0 sends makes no difference. Not caused by timing: reproduces with no delay
between turns. It happens in roughly 10-50% of conversations, varying from run to run.
Repro
Attached gemini_reroot_repro.py (self-contained; needs GEMINI_API_KEY):
uv run gemini_reroot_repro.py
It exits 1 when it catches the bug. Each run may not catch it; re-run or pass --conversations 16.
Example run
Excerpt: conversations that hit the bug are shown in full; 8 clean and 2 re-rooted without a rejection omitted. The full log is attached as gemini_reroot_bug_report.log.
==============================================================================
Gemini Interactions API -- conversation re-root breaks previous_interaction_id
==============================================================================
google-genai : 2.25.0
python : 3.13.11
model : gemini-3.8-flash
started (UTC): 2026-09-22T19:43:36Z
An interaction id is v1_<base64 protobuf>: field 1 is the conversation ROOT id, field 2
is the interaction's OWN id. They should match only on a conversation's first turn.
Running 12 conversations concurrently; each prints its table when it
finishes. >> = re-rooted (root == self mid-chain) XX = function_result rejected
Conversation 11 -- HIT THE BUG
turn status calls root (field 1) self (field 2) chained from (prev self) interaction id
-----------------------------------------------------------------------------------------------------------------------
1 start 1 aNqyapjKNdW7qtsPq9nq4QU aNqyapjKNdW7qtsPq9nq4QU (none) v1_ChdhTnF5YXBqS05kVzdxdHNQcTlucTRRVRIXYU5xeWFwaktOZFc3cXRzUHE5bnE0UVU
>> 2 RE-ROOTED 1 a9qyaqDwEYjsz7IPiY2foQU a9qyaqDwEYjsz7IPiY2foQU aNqyapjKNdW7qtsPq9nq4QU v1_ChdhOXF5YXFEd0VZanN6N0lQaVkyZm9RVRIXYTlxeWFxRHdFWWpzejdJUGlZMmZvUVU
3 ok 1 a9qyaqDwEYjsz7IPiY2foQU bdqyasjfIfeHqtsPo5LB-Qk a9qyaqDwEYjsz7IPiY2foQU v1_ChdhOXF5YXFEd0VZanN6N0lQaVkyZm9RVRIXYmRxeWFzamZJZmVIcXRzUG81TEItUWs
XX 4 REJECTED - - - bdqyasjfIfeHqtsPo5LB-Qk (rejected - no interaction created)
>> RE-ROOTED at turn 2: root (field 1) became the interaction's own id, so the server started a new conversation root mid-chain.
XX REJECTED at turn 4: submitting the function_result chained off the previous interaction failed with:
Please ensure that function response turn comes immediately after a function call turn. Got function response with name 'run_travel_code'.
Conversation 6 -- HIT THE BUG
turn status calls root (field 1) self (field 2) chained from (prev self) interaction id
-----------------------------------------------------------------------------------------------------------------------
1 start 1 adqyavisAbTmz7IPqLPtqQQ adqyavisAbTmz7IPqLPtqQQ (none) v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYWRxeWF2aXNBYlRtejdJUHFMUHRxUVE
2 ok 1 adqyavisAbTmz7IPqLPtqQQ atqyaovUOMGoqtsPp9-n8A0 adqyavisAbTmz7IPqLPtqQQ v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYXRxeWFvdlVPTUdvcXRzUHA5LW44QTA
3 ok 1 adqyavisAbTmz7IPqLPtqQQ bdqyauPqAZOxqtsPo_6E6A0 atqyaovUOMGoqtsPp9-n8A0 v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYmRxeWF1UHFBWk94cXRzUG9fNkU2QTA
>> 4 RE-ROOTED 1 cNqyata5JY6sz7IP8K7uoAg cNqyata5JY6sz7IP8K7uoAg bdqyauPqAZOxqtsPo_6E6A0 v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXY05xeWF0YTVKWTZzejdJUDhLN3VvQWc
5 ok 1 cNqyata5JY6sz7IP8K7uoAg dNqyauqgPOzzz7IP5Z2x4AQ cNqyata5JY6sz7IP8K7uoAg v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXZE5xeWF1cWdQT3p6ejdJUDVaMng0QVE
XX 6 REJECTED - - - dNqyauqgPOzzz7IP5Z2x4AQ (rejected - no interaction created)
>> RE-ROOTED at turn 4: root (field 1) became the interaction's own id, so the server started a new conversation root mid-chain.
XX REJECTED at turn 6: submitting the function_result chained off the previous interaction failed with:
Please ensure that function response turn comes immediately after a function call turn. Got function response with name 'run_travel_code'.
==============================================================================
re-rooted mid-chain : 4/12
rejected submissions: 2/12
==============================================================================
Controls against the rejected interaction
v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXZE5xeWF1cWdQT3p6ejdJUDVaMng0QVE
[0] its stored steps: function_result -> thought -> function_call
it ends in a function_call, so answering with a function_result is legal
[1.1] replay of the rejected request: rejected again
[1.2] replay of the rejected request: rejected again
[2] same interaction with PLAIN TEXT input: accepted
[3] SAME history sent EXPLICITLY (15 steps, no previous_interaction_id): ACCEPTED
=> the content is valid; only the server's chain reconstruction is wrong
gemini_reroot_bug_report.log
gemini_reroot_repro.py
Interactions API: previous_interaction_id chain re-roots mid-conversation, then rejects a valid function_result
Model: gemini-3.8-flash · Endpoint: POST /v1beta/interactions (streaming) · SDK: google-genai 2.8.0 and 2.25.0 (same result) · Reproduced: 2026-09-22
Summary
In a tool-calling conversation chained only with previous_interaction_id, the server
sometimes starts a new conversation root partway through. Two interactions later,
answering the pending function_call with a function_result fails with:
The client's request is valid. The interaction being chained off ends in a function_call,
and the function_result answers that call's id.
How the re-root shows up
An interaction id is v1_<urlsafe base64 protobuf>: field 1 is the conversation root id and
field 2 is the interaction's own id. They should be equal only on a conversation's first
interaction. In failing runs they become equal mid-chain (RE-ROOTED below). The
rejection follows two interactions later, when the rebuilt history seems to start with a
function_result whose function_call belongs to the old root.
Evidence it is server-side
Checked against the rejected interaction:
previous_interaction_id, is accepted. Same content, so only the server-side chain
reconstruction is wrong.
Not caused by the SDK: reproduces on 2.8.0 and 2.25.0, and toggling the api-revision
header 2.8.0 sends makes no difference. Not caused by timing: reproduces with no delay
between turns. It happens in roughly 10-50% of conversations, varying from run to run.
Repro
Attached gemini_reroot_repro.py (self-contained; needs GEMINI_API_KEY):
It exits 1 when it catches the bug. Each run may not catch it; re-run or pass --conversations 16.
Example run
Excerpt: conversations that hit the bug are shown in full; 8 clean and 2 re-rooted without a rejection omitted. The full log is attached as gemini_reroot_bug_report.log.
============================================================================== Gemini Interactions API -- conversation re-root breaks previous_interaction_id ============================================================================== google-genai : 2.25.0 python : 3.13.11 model : gemini-3.8-flash started (UTC): 2026-09-22T19:43:36Z An interaction id is v1_<base64 protobuf>: field 1 is the conversation ROOT id, field 2 is the interaction's OWN id. They should match only on a conversation's first turn. Running 12 conversations concurrently; each prints its table when it finishes. >> = re-rooted (root == self mid-chain) XX = function_result rejected Conversation 11 -- HIT THE BUG turn status calls root (field 1) self (field 2) chained from (prev self) interaction id ----------------------------------------------------------------------------------------------------------------------- 1 start 1 aNqyapjKNdW7qtsPq9nq4QU aNqyapjKNdW7qtsPq9nq4QU (none) v1_ChdhTnF5YXBqS05kVzdxdHNQcTlucTRRVRIXYU5xeWFwaktOZFc3cXRzUHE5bnE0UVU >> 2 RE-ROOTED 1 a9qyaqDwEYjsz7IPiY2foQU a9qyaqDwEYjsz7IPiY2foQU aNqyapjKNdW7qtsPq9nq4QU v1_ChdhOXF5YXFEd0VZanN6N0lQaVkyZm9RVRIXYTlxeWFxRHdFWWpzejdJUGlZMmZvUVU 3 ok 1 a9qyaqDwEYjsz7IPiY2foQU bdqyasjfIfeHqtsPo5LB-Qk a9qyaqDwEYjsz7IPiY2foQU v1_ChdhOXF5YXFEd0VZanN6N0lQaVkyZm9RVRIXYmRxeWFzamZJZmVIcXRzUG81TEItUWs XX 4 REJECTED - - - bdqyasjfIfeHqtsPo5LB-Qk (rejected - no interaction created) >> RE-ROOTED at turn 2: root (field 1) became the interaction's own id, so the server started a new conversation root mid-chain. XX REJECTED at turn 4: submitting the function_result chained off the previous interaction failed with: Please ensure that function response turn comes immediately after a function call turn. Got function response with name 'run_travel_code'. Conversation 6 -- HIT THE BUG turn status calls root (field 1) self (field 2) chained from (prev self) interaction id ----------------------------------------------------------------------------------------------------------------------- 1 start 1 adqyavisAbTmz7IPqLPtqQQ adqyavisAbTmz7IPqLPtqQQ (none) v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYWRxeWF2aXNBYlRtejdJUHFMUHRxUVE 2 ok 1 adqyavisAbTmz7IPqLPtqQQ atqyaovUOMGoqtsPp9-n8A0 adqyavisAbTmz7IPqLPtqQQ v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYXRxeWFvdlVPTUdvcXRzUHA5LW44QTA 3 ok 1 adqyavisAbTmz7IPqLPtqQQ bdqyauPqAZOxqtsPo_6E6A0 atqyaovUOMGoqtsPp9-n8A0 v1_ChdhZHF5YXZpc0FiVG16N0lQcUxQdHFRURIXYmRxeWF1UHFBWk94cXRzUG9fNkU2QTA >> 4 RE-ROOTED 1 cNqyata5JY6sz7IP8K7uoAg cNqyata5JY6sz7IP8K7uoAg bdqyauPqAZOxqtsPo_6E6A0 v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXY05xeWF0YTVKWTZzejdJUDhLN3VvQWc 5 ok 1 cNqyata5JY6sz7IP8K7uoAg dNqyauqgPOzzz7IP5Z2x4AQ cNqyata5JY6sz7IP8K7uoAg v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXZE5xeWF1cWdQT3p6ejdJUDVaMng0QVE XX 6 REJECTED - - - dNqyauqgPOzzz7IP5Z2x4AQ (rejected - no interaction created) >> RE-ROOTED at turn 4: root (field 1) became the interaction's own id, so the server started a new conversation root mid-chain. XX REJECTED at turn 6: submitting the function_result chained off the previous interaction failed with: Please ensure that function response turn comes immediately after a function call turn. Got function response with name 'run_travel_code'. ============================================================================== re-rooted mid-chain : 4/12 rejected submissions: 2/12 ============================================================================== Controls against the rejected interaction v1_ChdjTnF5YXRhNUpZNnN6N0lQOEs3dW9BZxIXZE5xeWF1cWdQT3p6ejdJUDVaMng0QVE [0] its stored steps: function_result -> thought -> function_call it ends in a function_call, so answering with a function_result is legal [1.1] replay of the rejected request: rejected again [1.2] replay of the rejected request: rejected again [2] same interaction with PLAIN TEXT input: accepted [3] SAME history sent EXPLICITLY (15 steps, no previous_interaction_id): ACCEPTED => the content is valid; only the server's chain reconstruction is wronggemini_reroot_bug_report.log
gemini_reroot_repro.py