666ghj/MiroFish · error · RuntimeError
Zep batch creation is unconfirmed and no matching operation
Error message
Zep batch creation is unconfirmed and no matching operation was found
What it means
RuntimeError in submit_document_batch: client.batch.create raised a retryable error (per is_retryable_zep_error), so the code tried to reconcile by listing batches for the deterministic operation_id — and found none. That means the create likely never reached the server (or is not yet visible), so there is no batch identity to continue with and the operation cannot be confirmed; raising prevents silently re-POSTing and risking duplicates.
Source
Thrown at backend/app/services/graph_builder.py:448
# Journal the deterministic operation before the server-generated
# batch ID POST. This leaves enough identity for later diagnosis
# even if both the response and immediate list reconciliation fail.
batch_created_callback(None, operation_id)
try:
batch = self.client.batch.create(
metadata={
"mirofish_operation_id": operation_id,
"graph_id": graph_id,
"chunk_count": total_chunks,
}
)
except Exception as error:
if not is_retryable_zep_error(error):
raise
batch = self._find_batch_by_operation_id(graph_id, operation_id)
if batch is None:
raise RuntimeError(
"Zep batch creation is unconfirmed and no matching operation was found"
) from error
batch_id = getattr(batch, "batch_id", None)
if not batch_id:
raise RuntimeError("Zep Batch API returned no batch_id")
if batch_created_callback:
batch_created_callback(batch_id, operation_id)
episode_uuids: List[str] = []
for i in range(0, total_chunks, batch_size):
batch_chunks = chunks[i:i + batch_size]
batch_num = i // batch_size + 1
total_batches = (total_chunks + batch_size - 1) // batch_size
if progress_callback:
progress = (i + len(batch_chunks)) / total_chunks
progress_callback(
t('progress.sendingBatch', current=batch_num, total=total_batches, chunks=len(batch_chunks)),View on GitHub (pinned to b5b53acc57)
Solutions
- Simply retry the whole build submission once connectivity recovers — no batch exists, so a fresh create is safe (the operation_id journal plus match-check protects against duplicates).
- Check Zep Cloud status and the API key's quota/rate limits if 429/503 appears in the chained error.
- If it recurs, increase the reconcile attempts/backoff in _find_batch_by_operation_id to ride out listing lag.
- Verify no proxy between backend and Zep is eating POST bodies or timing out the create.
- Inspect the chained cause (raise ... from error) to distinguish 'never sent' from 'sent but unlisted'.
Example fix
# before
batch = self._find_batch_by_operation_id(graph_id, operation_id)
if batch is None:
raise RuntimeError("Zep batch creation is unconfirmed and no matching operation was found") from error
# after - retry create once when reconcile proves nothing was created
batch = self._find_batch_by_operation_id(graph_id, operation_id)
if batch is None:
if create_attempted_once:
raise RuntimeError(
"Zep batch creation is unconfirmed and no matching operation was found"
) from error
batch = self.client.batch.create(metadata={"mirofish_operation_id": operation_id, "graph_id": graph_id})
create_attempted_once = True Defensive patterns
Strategy: retry
Try / catch
for attempt in range(3):
try:
submission = builder.submit_document_batch(graph_id, chunks, batch_size=bs)
break
except RuntimeError as e:
if 'unconfirmed and no matching operation' in str(e) and attempt < 2:
time.sleep(2 ** attempt)
continue # safe: reconcile proved no batch was created
raise Prevention
- Rely on the deterministic operation_id journal — retrying after a proven no-create is safe; blind re-POSTs are not.
- Monitor Zep Cloud status and API-key rate limits when create starts failing with retryable codes.
- Give _find_batch_by_operation_id enough attempts/backoff to ride out listing lag.
- Always inspect the chained cause to distinguish never-sent from unlisted.
When it happens
Trigger: Network failure/timeout before the create request reached Zep; the create was rejected server-side with a retryable-looking status (e.g. 429/503) after no side effects; list-batch eventual consistency delaying the new batch's appearance past the reconcile attempts; Zep Cloud outage.
Common situations: Flaky upstream connectivity during long document builds; Zep Cloud incident returning 5xx; rate limiting (429) on batch creation; retries exhausted because _find_batch_by_operation_id's sleep-backoff is short relative to Zep's listing lag.
Related errors
- Zep batch {batch_id} processing is unconfirmed
- Persisted Zep batch does not match the current graph input
- Multiple Zep batches match operation {operation_id}; refusin
- Zep Batch API returned no batch_id
- Zep batch {batch_id} item submission is unconfirmed; the dra
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/30ca5e392bafe5ee.
Report an issue: GitHub.