Skip to content

fix: #3348 AdvancedSQLiteSession.add_items silent partial save#3379

Open
john-rocky wants to merge 2 commits into
openai:mainfrom
john-rocky:fix/3348-add-items-atomicity
Open

fix: #3348 AdvancedSQLiteSession.add_items silent partial save#3379
john-rocky wants to merge 2 commits into
openai:mainfrom
john-rocky:fix/3348-add-items-atomicity

Conversation

@john-rocky
Copy link
Copy Markdown

Summary

AdvancedSQLiteSession.add_items first inserted the base message rows, committed them, and only then wrote message_structure rows. If the structure write failed, the matching conn.rollback() was a no-op because the base rows were already committed. A best-effort orphan cleanup ran next, but the original exception was always swallowed by self._logger.error(...), so the caller saw a successful add_items() even though:

  • get_items() (which joins through message_structure) returned the rows as missing, and
  • when the cleanup itself failed, the base table kept invisible orphan rows that no advanced read could ever surface.

The fix is to share a single transaction for both writes and let the original exception propagate. _insert_structure_metadata already reads back the just-inserted message IDs through a SELECT, which SQLite serves from the uncommitted state of the same transaction, so no intermediate commit is needed for correctness — only the false success was load-bearing.

Test plan

Added test_add_items_rolls_back_when_structure_metadata_fails. It subclasses AdvancedSQLiteSession with a toggleable _insert_structure_metadata that fails the first time and succeeds on retry, and verifies that:

  • the failing call raises RuntimeError,
  • both get_items() and direct counts on <messages_table> and message_structure come back empty,
  • a follow-up call with the failure cleared persists the message normally.
$ uv run pytest tests/extensions/memory/test_advanced_sqlite_session.py
============================== 37 passed in 0.19s ==============================
$ make format
All checks passed!
$ make lint
All checks passed!
$ uv run mypy src/agents/extensions/memory/advanced_sqlite_session.py tests/extensions/memory/test_advanced_sqlite_session.py
Success: no issues found in 2 source files

Issue number

Closes #3348. Related to #3346 (orphan rows after delete_branch), which is a separate path and not touched here.

Checks

  • I've added new tests (if relevant)
  • I've added/updated the relevant documentation
  • I've run `make lint` and `make format`
  • I've made sure tests pass

`_type_to_str` unconditionally read `__name__` on each typing arg, which
raised `AttributeError` for `Literal["ok"]` because the literal value is a
`str` instance rather than a class. The schema itself built fine but
`name()` (and therefore the agent trace path) crashed when starting a run
with a structured output type that contained any literal.

Fall back to `repr()` for non-type args and to `_name`/`str(origin)` for
typing constructs that lack `__name__`. Adds a focused regression test for
`Literal["ok"]`, multi-member `Literal`, nested `list[Literal[...]]`, and
non-string `Literal[1, 2]` cases.

Fixes openai#3357.
`add_items` previously committed the base message rows before writing the
`message_structure` rows. If the structure write raised, the base rows had
already been committed, so the rollback at that point was a no-op. Best-effort
cleanup deleted the orphans when it worked, but masked the original error
either way; when cleanup itself failed, callers got a silent success and the
base table kept invisible orphan rows that advanced reads (joined through
`message_structure`) could never see.

Both writes now share a single transaction and the original exception
propagates to the caller, so retries see either a fully landed batch or a
clean slate.

Fixes openai#3348.
@seratch seratch added duplicate This issue or pull request already exists feature:sessions labels May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists feature:sessions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AdvancedSQLiteSession.add_items can report success after structure metadata failure

2 participants