{"record":{"id":"e9fc9a3df4d7077d","repo":"langflow-ai/langflow","slug":"cannot-change-fs-path-of-a-flow-you-do-not-own","errorCode":null,"errorMessage":"Cannot change fs_path of a flow you do not own.","messagePattern":"Cannot change fs_path 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":420,"sourceCode":"    \"\"\"\n    await lock_flow_for_update(session, existing_flow)\n\n    settings_service = get_settings_service()\n    actor_user_id = current_user.id\n    owner_user_id: UUID = existing_flow.user_id\n    is_owner_edit = owner_user_id == actor_user_id\n\n    # Non-owner edits cannot relocate the flow into folders or storage they\n    # own, nor transfer ownership. Reject early so the failure is explicit\n    # rather than corrupting scope downstream.\n    if not is_owner_edit:\n        if flow.folder_id is not None and flow.folder_id != existing_flow.folder_id:\n            raise HTTPException(\n                status_code=403,\n                detail=\"Cannot change folder of a flow you do not own.\",\n            )\n        if flow.fs_path is not None and flow.fs_path != existing_flow.fs_path:\n            raise HTTPException(\n                status_code=403,\n                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","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/flows_helpers.py#L402-L438","documentation":"HTTP 403 from _update_flow: a non-owner edit attempts to change fs_path to a value different from the stored one. Storage location is part of the flow's scope (fs_path lives under the owner's namespace and is even validated against owner_user_id), so non-owner editors cannot redirect where the flow is persisted.","triggerScenarios":"PATCH/PUT by a non-owner (plugin-authorized editor or service account) whose payload includes an fs_path different from existing_flow.fs_path.","commonSituations":"A shared/team flow where an editor tries to move persistence to their own directory; sync tooling running as a service account that blindly includes fs_path on every update.","solutions":["Omit fs_path from non-owner updates.","Send fs_path exactly equal to the current value if your client echoes it back, or strip it from the payload.","Have the owner perform any storage relocation."],"exampleFix":"// before — client echoes every field\nbody = {...flow, fs_path: myPath};\n// after\nif (!isOwner) delete body.fs_path;","handlingStrategy":"validation","validationCode":"if (!isOwner && 'fs_path' in body && body.fs_path !== currentFlow.fs_path) delete body.fs_path;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit fs_path on non-owner updates","Echo the exact current value if the field must be present","Remember validation is scoped to the owner's namespace"],"tags":["authorization","ownership","http-403","fs-path","rbac"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}