Significant-Gravitas/AutoGPT · warning · HTTPException
Graph ID does not match ID in URI
Error message
Graph ID does not match ID in URI
What it means
Raised (400) by PUT /graphs/{graph_id} when the request body carries a non-null graph.id that differs from the graph_id in the URI. The API treats the path parameter as authoritative; a body/URI mismatch is rejected to prevent accidentally overwriting a different graph.
Source
Thrown at autogpt_platform/backend/backend/api/features/v1.py:1801
graph_id, user_id=user_id, organization_id=ctx.org_id
)
}
@v1_router.put(
path="/graphs/{graph_id}",
summary="Update graph version",
tags=["graphs"],
dependencies=[Security(requires_user)],
)
async def update_graph(
graph_id: str,
graph: graph_db.Graph,
user_id: Annotated[str, Security(get_user_id)],
ctx: Annotated[RequestContext, Security(get_request_context)],
) -> UpdateGraphResponse:
if graph.id and graph.id != graph_id:
raise HTTPException(400, detail="Graph ID does not match ID in URI")
existing_versions = await graph_db.get_graph_all_versions(graph_id, user_id=user_id)
if not existing_versions:
raise HTTPException(404, detail=f"Graph #{graph_id} not found")
graph.version = max(g.version for g in existing_versions) + 1
current_active_version = next((v for v in existing_versions if v.is_active), None)
graph = graph_db.make_graph_model(graph, user_id)
graph.reassign_ids(user_id=user_id, reassign_graph_id=False)
graph.validate_graph(for_run=False)
# If this new version is going to be active, validate node credentials
# BEFORE persisting so a credential issue can't leave a half-saved version
# behind. before_graph_activate may also clear stale optional credentials —
# those edits must be persisted, hence the pre-save call.
if graph.is_active:
graph = await before_graph_activate(graph, user_id=user_id)View on GitHub (pinned to 9c8bb5550f)
Solutions
- Make the body's id match the URI (or omit graph.id entirely — null is allowed and the URI wins).
- In the frontend, key graph-editing state by graph_id so switching graphs resets the payload.
- For duplication flows use the dedicated create endpoint instead of PUT with a foreign id.
Example fix
// before
await api.updateGraph(graphId, { ...staleGraph, id: staleGraph.id });
// after
await api.updateGraph(graphId, { ...staleGraph, id: graphId });
// or omit id: await api.updateGraph(graphId, { ...graph, id: null }); Defensive patterns
Strategy: validation
Validate before calling
if (payload.id && payload.id !== routeGraphId) {
throw new Error(`Body graph id ${payload.id} != URI ${routeGraphId}`);
}
await api.updateGraph(routeGraphId, { ...payload, id: routeGraphId }); Type guard
const idsAgree = (bodyId: string | null | undefined, uriId: string) => !bodyId || bodyId === uriId;
Try / catch
catch (e) { if (e.response?.status === 400 && /does not match/.test(e.response.data.detail)) { resyncGraphStateFromServer(); } else throw e; } Prevention
- Derive the URL and the payload id from the same piece of state; never mix sources.
- Reset editing state when switching graphs in the builder.
- Omit graph.id from update payloads unless you explicitly round-trip it from a GET of the same ID.
When it happens
Trigger: PUT /graphs/aaa-... with body {"id": "bbb-...", ...} — typically a frontend bug that saved graph A's draft into state and submitted it against graph B's URL, or a copy-paste of a graph JSON into an update call against another graph's route.
Common situations: Builder UI state desync when switching between graphs quickly; 'duplicate then edit' flows that keep the source graph's id in the payload; API clients templating the URL and body from different sources.
Related errors
- validation_error
- Unsupported grant_type: {request.grant_type}. Must be 'autho
- start and end query params are required
- str(exc)
- Either user_id or email query parameter is required.
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/2c561291736fb3ed.
Report an issue: GitHub.