Regression tests added (2 new at tick 106, in tests/testdelete404.py):
Root cause (GAP-019 / tick 106): The DELETE handler for DELETE /v1/sessions/{id} called store.delete() unconditionally and returned 200 OK even when the id wasn't a tracked session, while GET /v1/sessions/{id} and POST /v1/sessions/{id}/cancel both returned 404. The three verbs validated session existence through different code paths, so behavior drifted.
The fix: Route all three verbs through one shared existence gate — a require_tracked_session dependency that resolves the session (or raises 404) before the handler runs. DELETE now 404s unknown tracked sessions instead of silently succeeding.
Before (buggy):
@router.delete("/v1/sessions/{session_id}", response_model=DeleteOut)
def delete_session(session_id: str) -> DeleteOut:
store.delete(session_id) # BUG: no existence check — unknown ids return 200
return DeleteOut(status="deleted")
After (fixed, tick 106):
from fastapi import APIRouter, Depends, HTTPException
def require_tracked_session(session_id: str) -> Session:
"""Shared existence gate — single source of truth for session validation."""
session = store.get(session_id)
if session is None:
raise HTTPException(status_code=404, detail=f"session '{session_id}' not found")
return session
@router.get("/v1/sessions/{session_id}", response_model=SessionOut)
def get_session(session: Session = Depends(require_tracked_session)) -> SessionOut:
return SessionOut(id=session.id, state=session.state)
@router.post("/v1/sessions/{session_id}/cancel", response_model=SessionOut)
def cancel_session(session: Session = Depends(require_tracked_session)) -> SessionOut:
store.cancel(session.id)
return SessionOut(id=session.id, state="cancelled")
@router.delete("/v1/sessions/{session_id}", response_model=DeleteOut)
def delete_session(session: Session = Depends(require_tracked_session)) -> DeleteOut:
# Fix: existence validated above; unknown ids never reach the handler.
store.delete(session.id)
return DeleteOut(status="deleted")
Regression tests added (2 new at tick 106, in tests/test_delete_404.py):
def test_delete_unknown_session_returns_404():
client = TestClient(_app(buggy=False))
resp = client.delete("/v1/sessions/does-not-exist-000")
assert resp.status_code == 404
assert "not found" in resp.json()["detail"].lower()
def test_get_cancel_delete_agree_on_unknown_session():
"""Consistency contract: all three verbs 404 for the same unknown id."""
client = TestClient(_app(buggy=False))
unknown = "ghost-session-42"
assert client.get(f"/v1/sessions/{unknown}").status_code == 404
assert client.post(f"/v1/sessions/{unknown}/cancel").status_code == 404
assert client.delete(f"/v1/sessions/{unknown}").status_code == 404
I reproduced the bug against a pre-fix router, applied the fix, and ran the full suite with `pytest` (FastAPI + TestClient, Python 3.14). **Result: 6 passed, 0 failed** in 0.37s. **Live before/after diff** (actual HTTP status codes): ``` --- BEFORE fix (tick < 106) --- DELETE known /v1/sessions/e5a7d9… -> 200 DELETE unknown /v1/sessions/ghost-1 -> 200 ← bug (should be 404) GET unknown /v1/sessions/ghost-1 -> 404 CANCEL unknown /v1/sessions/ghost-1 -> 404 --- AFTER fix (tick 106) --- DELETE known /v1/sessions/9b801f… -> 200 DELETE unknown /v1/sessions/ghost-1 -> 404 ← consistent GET unknown /v1/sessions/ghost-1 -> 404 CANCEL unknown /v1/sessions/ghost-1 -> 404 ``` **Test matrix (edge cases covered):** | Test | Verifies | |---|---| | `test_buggy_delete_unknown_session_returned_200` | Reproduces the original bug (buggy router returns 200) — guards the regression test itself | | `test_delete_unknown_session_returns_404` | **New:** unknown id → 404 with a `not found` detail body | | `test_delete_known_session_returns_200_and_removes_it` | **New:** known id → 200, then the *same* id is 404 on a second delete (real removal, not a no-op) | | `test_get_cancel_delete_agree_on_unknown_session` | Cross-verb consistency on unknown ids (GET / cancel / DELETE all 404) | | `test_get_cancel_delete_agree_on_tracked_session` | Cross-verb consistency on tracked ids (all 200) | | `test_delete_is_idempotent_for_existing_but_404_after_first_delete` | Idempotency semantics: first delete 200, subsequent delete 404, GET after delete 404 | Edge cases deliberately exercised: unknown id vs. known id, deletion of a freshly created session, double-delete of the same id, and parity across all three verbs for both existing and nonexistent sessions. The `404` body carries a useful `detail` (`session '<id>' not found`) for the Python SDK client to surface as a typed error rather than a silent success. Full run output: ``` tests/test_delete_404.py::test_buggy_delete_unknown_session_returned_200 PASSED tests/test_delete_404.py::test_delete_unknown_session_returns_404 PASSED tests/test_delete_404.py::test_delete_known_session_returns_200_and_removes_it PASSED tests/test_delete_404.py::test_get_cancel_delete_agree_on_unknown_session PASSED tests/test_delete_404.py::test_get_cancel_delete_agree_on_tracked_session PASSED tests/test_delete_404.py::test_delete_is_idempotent_for_existing_but_404_after_first_delete PASSED =========================== 6 passed, 1 warning in 0.37s =========================== ``` ---
{"model": "deepseek-v4-flash", "problem_class": "python-sdk-delete-404", "result": "passed", "tests": 6}