Clawpatch finding
- Severity: medium
- Category: data-loss
- Confidence: high
- Feature:
feat_custom_apis_openai_responses_state_store_stream
- Finding ID:
fnd_sig-feat-custom-apis-openai-resp_c1f129c457
- Run ID:
20260831T084818-f6ae5e
- Reviewer model:
gpt-5.6-sol via the local Codex provider at xhigh
- Prior overlap: No matching GitHub issue or prior-run finding was found.
Evidence
apis/src/openai/responses/stream_events/mod.rs:253-269 (record_completion)
apis/src/openai/responses/stream_events/accumulator.rs:50-52 (accumulate_event)
apis/src/openai/responses/store/filter.rs:259-269 (ResponseStoreFilter::persist_from_streaming_state)
apis/src/openai/responses/stream_events/tests.rs:704-725 (error_after_terminal_lifecycle_is_accepted)
Description
response.completed is represented internally as a terminal lifecycle state, but the first following error event is specially accepted. The completed response object remains in ResponsesState, no parse-error or incomplete metadata is set, and the store therefore persists it as a successful completed response. Rehydration can later treat that record as a valid predecessor even though the stream subsequently reported an error.
Reproduction
Process a streaming create response containing a valid response.completed event, then an error event, then end-of-stream. Run the response-store body hook. The stream has no responses.stream_parse_error or responses.stream_incomplete marker and the completed response object is eligible for persistence.
Recommendation
Allow an error event only while completion state is Open. Treat any event, including the first error, after TerminalLifecycle as EventAfterTerminal so responses.stream_parse_error is set and persistence is skipped.
Reported from a Clawpatch review of apis/src at commit 543259683b9ff9a3f42772703a6d9ca134948475.
Clawpatch finding
feat_custom_apis_openai_responses_state_store_streamfnd_sig-feat-custom-apis-openai-resp_c1f129c45720260831T084818-f6ae5egpt-5.6-solvia the local Codex provider atxhighEvidence
apis/src/openai/responses/stream_events/mod.rs:253-269(record_completion)apis/src/openai/responses/stream_events/accumulator.rs:50-52(accumulate_event)apis/src/openai/responses/store/filter.rs:259-269(ResponseStoreFilter::persist_from_streaming_state)apis/src/openai/responses/stream_events/tests.rs:704-725(error_after_terminal_lifecycle_is_accepted)Description
response.completedis represented internally as a terminal lifecycle state, but the first followingerrorevent is specially accepted. The completed response object remains inResponsesState, no parse-error or incomplete metadata is set, and the store therefore persists it as a successful completed response. Rehydration can later treat that record as a valid predecessor even though the stream subsequently reported an error.Reproduction
Process a streaming create response containing a valid
response.completedevent, then anerrorevent, then end-of-stream. Run the response-store body hook. The stream has noresponses.stream_parse_errororresponses.stream_incompletemarker and the completed response object is eligible for persistence.Recommendation
Allow an
errorevent only while completion state isOpen. Treat any event, including the first error, afterTerminalLifecycleasEventAfterTerminalsoresponses.stream_parse_erroris set and persistence is skipped.Reported from a Clawpatch review of
apis/srcat commit543259683b9ff9a3f42772703a6d9ca134948475.