{"record":{"id":"31f863fd32b35816","repo":"langflow-ai/langflow","slug":"cannot-change-a2a-card-overrides-of-a-flow-you-do","errorCode":null,"errorMessage":"Cannot change a2a_card_overrides of a flow you do not own.","messagePattern":"Cannot change a2a_card_overrides of a flow you do not own\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"src/backend/base/langflow/api/v1/flows_helpers.py","lineNumber":440,"sourceCode":"                detail=\"Cannot change fs_path of a flow you do not own.\",\n            )\n        if flow.user_id is not None and flow.user_id != owner_user_id:\n            raise HTTPException(\n                status_code=403,\n                detail=\"Cannot transfer ownership of a flow you do not own.\",\n            )\n        # ``a2a_enabled`` defaults to False (not None) on FlowCreate, so gate on\n        # model_fields_set to block only an explicit, differing change.\n        if \"a2a_enabled\" in flow.model_fields_set and flow.a2a_enabled != existing_flow.a2a_enabled:\n            raise HTTPException(\n                status_code=403,\n                detail=\"Cannot change a2a_enabled of a flow you do not own.\",\n            )\n        if (\n            \"a2a_card_overrides\" in flow.model_fields_set\n            and flow.a2a_card_overrides != existing_flow.a2a_card_overrides\n        ):\n            raise HTTPException(\n                status_code=403,\n                detail=\"Cannot change a2a_card_overrides of a flow you do not own.\",\n            )\n\n    # Validate fs_path if provided (use `is not None` to catch empty strings).\n    # Path safety is scoped to the *owner* — fs_path lives under the owner's\n    # storage namespace, so we must not authorize it against the actor's.\n    if flow.fs_path is not None:\n        await _verify_fs_path(flow.fs_path, owner_user_id, storage_service)\n\n    # Validate folder_id if provided — scoped to the owner so a non-owner\n    # cannot land the flow in their own default folder via this code path.\n    if flow.folder_id is not None:\n        folder = (\n            await session.exec(select(Folder).where(Folder.id == flow.folder_id, Folder.user_id == owner_user_id))\n        ).first()\n        if not folder:\n            raise HTTPException(status_code=400, detail=\"Folder not found\")","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/flows_helpers.py#L422-L458","documentation":"HTTP 403 from _update_flow: a non-owner edit explicitly changes a2a_card_overrides (the AgentCard customization for A2A) to a value differing from the stored one. Like a2a_enabled it is gated on model_fields_set, so only explicit, differing changes by non-owners are rejected; it exists because card overrides control how the flow is advertised to external A2A agents.","triggerScenarios":"PATCH/PUT by a non-owner with a2a_card_overrides in the body whose value differs from existing_flow.a2a_card_overrides — e.g. changing the advertised name/description/authentication of another user's A2A flow.","commonSituations":"Central teams customising A2A cards across org-owned flows without being the row owner; sync clients that always resend the full card overrides object with minor formatting drift (which counts as a differing value).","solutions":["Omit a2a_card_overrides from non-owner update payloads.","If the client echoes the object back, send it byte-identical (equal values pass) or strip it.","Have the owner apply card override changes."],"exampleFix":"# before\n{\"a2a_card_overrides\": {\"name\": \"Team Agent\"}}   # non-owner\n# after\n{}                                               # owner applies overrides","handlingStrategy":"validation","validationCode":"if (!isOwner && 'a2a_card_overrides' in body && JSON.stringify(body.a2a_card_overrides) !== JSON.stringify(currentFlow.a2a_card_overrides)) delete body.a2a_card_overrides;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit a2a_card_overrides on non-owner edits","Send byte-identical values when echoing the card back","Formatting drift in echoed JSON counts as a change — strip the field instead"],"tags":["authorization","ownership","http-403","a2a","rbac"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}