666ghj/MiroFish · error · ValueError
graph_id is required
Error message
graph_id is required
What it means
ValueError in submit_document_batch (graph_builder.py): the method requires an existing Zep graph to attach batch episodes to, and an empty/None graph_id is rejected before any Cloud mutation. Graphs must be created first (create_graph) so the batch has a destination; this check deliberately fails before the batch_created_callback journaling fires, keeping state clean.
Source
Thrown at backend/app/services/graph_builder.py:424
def add_text_batches(
self,
graph_id: str,
chunks: List[str],
batch_size: int = 350,
progress_callback: Optional[Callable] = None,
batch_created_callback: Optional[Callable[[str | None, str], None]] = None,
) -> BatchSubmission:
"""Submit document chunks through Zep's current Batch API.
Mutating calls are deliberately not retried: create/add are not
documented as idempotent, and an ambiguous replay can duplicate graph
episodes. The returned batch identity allows callers to persist and
reconcile the operation instead.
"""
if not graph_id:
raise ValueError("graph_id is required")
self.validate_batch_chunks(chunks, batch_size=batch_size)
total_chunks = len(chunks)
operation_id = self.build_operation_id(graph_id, chunks)
if batch_created_callback:
# 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,
}
)View on GitHub (pinned to b5b53acc57)
Solutions
- Create the graph first (builder.create_graph / the endpoint that provisions it) and pass the returned graph_id.
- If resuming, verify project.graph_id is still set before calling submit; re-create the graph if it was cleared.
- Guard concurrent delete/rebuild vs submit with the same per-graph lifecycle lock used elsewhere.
- Add an assertion/log at the API layer so a None graph_id is caught with the project id in context.
Example fix
# before
def submit_document_batch(self, graph_id, chunks, *, batch_size=350, ...):
if not graph_id:
raise ValueError("graph_id is required")
# after - fail with context naming the caller's project state
def submit_document_batch(self, graph_id, chunks, *, batch_size=350, ...):
if not graph_id:
raise ValueError(
"graph_id is required: create the graph and persist its id before submitting a batch"
)
# caller
if not project.graph_id:
project.graph_id = builder.create_graph(name=project.name) Defensive patterns
Strategy: validation
Validate before calling
if not graph_id:
graph_id = builder.create_graph(name=project.name)
project.graph_id = graph_id
submission = builder.submit_document_batch(graph_id, chunks, batch_size=batch_size) Type guard
def has_graph_id(project) -> bool:
return bool(getattr(project, 'graph_id', None)) Try / catch
try:
builder.submit_document_batch(graph_id, chunks, batch_size=batch_size)
except ValueError as e:
if 'graph_id is required' in str(e):
raise HTTPException(status_code=409, detail='Project has no graph; create one first') from e
raise Prevention
- Provision the graph before any batch submission and persist its id on the project.
- Guard delete/rebuild vs submit with the same per-graph lifecycle lock.
- Assert project.graph_id is set at the API layer before calling the builder.
- Re-create the graph if a failed delete flow cleared graph_id mid-build.
When it happens
Trigger: Calling submit_document_batch with graph_id=None/'' because the caller skipped graph creation, the create call failed but the error was swallowed, or the project record's graph_id was cleared (e.g. by _clear_project_graph_reference) while a build was still being attempted.
Common situations: Race between graph deletion/rebuild and an in-flight document submission; caller assumes the service creates the graph implicitly; project row lost its graph_id after a failed delete flow.
Related errors
- At least one text chunk is required
- batch_size must be between 1 and 350
- A Zep batch cannot contain more than 50,000 items
- Graph {graph_id} is in use by active consumer(s): {', '.join
- Persisted Zep batch does not match the current graph input
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/17030b9360a3ec1c.
Report an issue: GitHub.