{"record":{"id":"b60874b16a6c789f","repo":"langflow-ai/langflow","slug":"flow-is-not-public","errorCode":null,"errorMessage":"Flow is not public","messagePattern":"Flow is not public","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"src/backend/base/langflow/api/utils/flow_utils.py","lineNumber":258,"sourceCode":"    Raises:\n        HTTPException:\n            - 400 if neither client_id nor authenticated_user_id is provided\n            - 403 if flow doesn't exist or isn't public\n            - 403 if unable to retrieve the flow owner user\n            - 403 if user is not found for public flow\n    \"\"\"\n    if not client_id and not authenticated_user_id:\n        raise HTTPException(status_code=400, detail=\"No client_id cookie found\")\n\n    # Check if the flow is public\n    async with session_scope() as session:\n        from sqlmodel import select\n\n        from langflow.services.database.models.flow.model import AccessTypeEnum, Flow\n\n        flow = (await session.exec(select(Flow).where(Flow.id == flow_id))).first()\n        if not flow or flow.access_type is not AccessTypeEnum.PUBLIC:\n            raise HTTPException(status_code=403, detail=\"Flow is not public\")\n\n    # Use authenticated user_id for deterministic UUID when available, otherwise client_id.\n    # Keep the branches explicit so identifier is non-optional at the UUID boundary.\n    if authenticated_user_id is not None:\n        identifier = str(authenticated_user_id)\n        principal_type: Literal[\"user\", \"client\"] = \"user\"\n    else:\n        if client_id is None:\n            raise HTTPException(status_code=400, detail=\"No client_id cookie found\")\n        identifier = client_id\n        principal_type = \"client\"\n    new_flow_id = compute_virtual_flow_id(identifier, flow_id, principal_type=principal_type)\n\n    # Get the user associated with the flow\n    try:\n        from langflow.helpers.user import get_user_by_flow_id_or_endpoint_name\n\n        user = await get_user_by_flow_id_or_endpoint_name(str(flow_id))","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/utils/flow_utils.py#L240-L276","documentation":"verify_public_flow_and_get_user() checks the flow exists in the database AND its access_type is AccessTypeEnum.PUBLIC; if either fails it raises 403 'Flow is not public'. The check runs before any session/virtual-flow-ID work, so a nonexistent flow id and a private flow id produce the same 403 (no existence oracle for private flows).","triggerScenarios":"Requesting execution of a flow whose access_type is PRIVATE (the default), or a flow id that was deleted or never existed, via an endpoint that routes through verify_public_flow_and_get_user — with a valid client_id/auth context but no owner permissions. Also triggered if the flow was unshared after a client cached the public URL.","commonSituations":"The developer forgot to flip the flow to Public in the Langflow UI's flow settings (Share -> Public) before sharing the link; the flow was deleted or its access reverted to private; using a copied endpoint URL from another workspace; DB queries failing to resolve after a migration or when pointing at the wrong database.","solutions":["Open the flow in Langflow, go to flow Settings/Share, and set Access Type to Public, then retry.","Verify the flow id in the URL matches an existing flow (GET /api/v1/flows/{id} as the owner).","If the flow must stay private, call it authenticated as the owner (or via an API key) rather than through the public playground path.","Check you are connected to the right database/environment — a missing flow row here also yields this 403."],"exampleFix":"# before: flow.access_type == PRIVATE\n# (UI) Flow Settings -> Access Type: Private  -> 403 on public run\n\n# after\n# (UI) Flow Settings -> Access Type: Public, then:\ncurl -b jar.txt -X POST https://host/api/v1/run/{flow_id} -d '{}'","handlingStrategy":"validation","validationCode":"async def flow_is_public(api, flow_id: str) -> bool:\n    r = await api.get(f'/api/v1/flows/{flow_id}')  # as owner / with token\n    return r.status_code == 200 and r.json().get('access_type') == 'PUBLIC'","typeGuard":null,"tryCatchPattern":"try:\n    user, vfid = await verify_public_flow_and_get_user(flow_id, client_id)\nexcept HTTPException as e:\n    if e.status_code == 403 and e.detail == 'Flow is not public':\n        raise RuntimeError('flip Access Type to Public in flow settings, or call authenticated as owner')\n    raise","preventionTips":["Set Access Type = Public in flow settings before sharing any link.","Automate a pre-share check: assert flow.access_type == 'PUBLIC' in your deploy script.","Treat 403 on public endpoints as a config signal, not a transient error — do not retry unchanged."],"tags":["public-flow","authorization","http-403","access-control","api"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}