Skip to content

fix(conversations): fail closed on append-back item loss (#837) - #860

Open
leseb wants to merge 1 commit into
praxis-proxy:mainfrom
leseb:leseb/fix-issue-837
Open

fix(conversations): fail closed on append-back item loss (#837)#860
leseb wants to merge 1 commit into
praxis-proxy:mainfrom
leseb:leseb/fix-issue-837

Conversation

@leseb

@leseb leseb commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Non-streaming Responses calls tied to a conversation_id persist their input/output items after the turn, but that append-back logged and swallowed any persistence error and still returned 200, silently dropping items so the next turn rehydrated an incomplete history (#837). This fails closed at the durability boundary: an item-insertion failure now propagates (the error reaches on_response_body before the buffered body is released, so under the default failure_mode: closed the body is withheld and the turn aborts instead of hiding the loss), while a post-commit message-cache refresh failure is logged and tolerated because that cache is a self-healing projection and failing would drive a retry that duplicates the id-less input items. A fault-injecting ConversationItemStore proves item-insert failure returns Err and message-cache refresh failure returns Continue.

Related issue

Closes #837

Validation

  • Unit tests — cargo test -p praxis-ai-apis (2590 passing), incl. on_response_body_surfaces_item_insert_failure (→ Err) and on_response_body_tolerates_message_cache_failure (→ Continue)
  • Integration or functional tests — n/a: no new capability; existing openai_conversations functional suite is unaffected (store-failure injection is not reachable through the proxy)
  • make lint (and make build)

Checklist

  • I reviewed every changed line and can explain the change.
  • New capabilities include an example config and functional example test. — n/a (bug fix, no new capability/config)
  • User-facing behavior and generated documentation are updated. — n/a (internal durability behavior; code comments updated)
  • Performance-sensitive changes include appropriate benchmark or load-test evidence. — n/a
  • Commits are signed and include a Signed-off-by trailer.

Breaking changes

Under the default failure_mode: closed, a conversation whose items fail to persist now aborts the turn (withheld body) instead of returning a success that hides the loss; operators wanting the prior best-effort behavior can set failure_mode: open on the filter. The transient message-cache stale window is unchanged — fully closing it (atomic item-insert + projection) is tracked separately.

…y#837)

Non-streaming Responses calls tied to a conversation_id persist the
input and output items after the turn completes. That append-back
logged and swallowed any persistence error and still returned 200, so
items could be silently dropped while the client saw success -- the
next turn then rehydrated an incomplete history (praxis-proxy#837).

Align fail-closed handling with the durability boundary:

- Item insertion is the source of truth: on failure, propagate the
  error. It reaches this point before the buffered response body is
  released, so under the default failure_mode: closed the body is
  withheld and the turn aborts instead of returning a success that
  hides lost items. Operators can still opt out with failure_mode: open.
- The denormalized message cache is a self-healing projection rebuilt
  from the items table, so a post-commit refresh failure is logged and
  tolerated: failing the turn would drive a client retry that
  re-appends the same (id-less) input items as duplicates.

Add a fault-injecting ConversationItemStore proving item-insert
failure returns Err while message-cache refresh failure returns
Continue. This does not close the transient stale-cache window; an
atomic item-insert + projection is tracked separately.

Signed-off-by: Sébastien Han <seb@redhat.com>
@leseb
leseb requested review from a team and aslakknutsen September 1, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conversation append-back failures are hidden behind successful Responses results

1 participant