Skip to content

fix(sessions): keep invalid adapter rows out of public listings - #1177

Open
GautamSharma99 wants to merge 1 commit into
anthropics:mainfrom
GautamSharma99:fix/1167-filter-invalid-store-session-ids
Open

fix(sessions): keep invalid adapter rows out of public listings#1177
GautamSharma99 wants to merge 1 commit into
anthropics:mainfrom
GautamSharma99:fix/1167-filter-invalid-store-session-ids

Conversation

@GautamSharma99

Copy link
Copy Markdown

Summary

Validate SessionStore listing rows at the SDK boundary so list_sessions_from_store() never exposes session IDs that the rest of the SDK rejects.

  • filter malformed IDs returned by list_sessions() before any load() call
  • filter malformed IDs returned by list_session_summaries() before conversion
  • keep invalid rows out of freshness matching, sorting, offset, and limit calculations
  • preserve behavior across slow, combined-fast, and summary-only adapters

Problem

Filesystem discovery validates transcript filenames as UUIDs, and individual store-backed lookups reject invalid session IDs. Store-backed listing was the exception: it trusted IDs from adapter indexes and summary sidecars without validation.

That allowed a malformed, stale, or externally populated row to:

  1. trigger a pointless store.load() call on the slow path
  2. become a public SDKSessionInfo
  3. occupy an offset or limit position ahead of valid sessions
  4. produce an ID that get, resume, fork, and mutation APIs subsequently reject
  5. raise unexpectedly if corrupt adapter data contained a non-string ID

Implementation

A shared _has_valid_store_session_id() predicate now checks that a listing row is a dictionary, its session_id is a string, and the value passes the existing SDK UUID validator.

The predicate is applied immediately after each adapter call:

  • slow-path list_sessions() results are filtered before concurrent loads
  • fast-path list_sessions() results are filtered before known_mtimes construction and gap-fill slot creation
  • list_session_summaries() results are filtered before freshness checks, summary_entry_to_sdk_info(), sorting, and pagination

Filtering is silent, matching filesystem session discovery, which skips non-UUID transcript filenames rather than failing the entire listing.

The adapter protocol remains unchanged. Stores may still contain externally managed or legacy rows; the public SDK listing simply declines to expose unusable IDs.

Pagination semantics

Invalid rows are removed before sorting, offset, and limit. A malformed row with the newest mtime therefore cannot consume a page position or cause a valid session to be skipped.

Tests

Added regression coverage for:

  • slow-path adapters returning invalid string and non-string IDs
  • proving invalid IDs never reach store.load()
  • proving an invalid newest row does not consume limit=1
  • combined fast-path adapters returning the invalid ID from both listing methods
  • summary-only adapters where list_sessions() is unavailable for cross-checking

Validation

  • uv run --extra dev pytest -q — 1297 passed, 5 skipped
  • uv run --extra dev ruff check src tests — passed
  • uv run --extra dev ruff format --check src tests — passed
  • uv run --extra dev mypy src — passed

Fixes #1167

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.

list_sessions_from_store exposes invalid session IDs returned by adapters

1 participant