langflow-ai/langflow · warning · HTTPException

Job not found

Error message

Job not found

What it means

Raised as HTTP 404 with static detail 'Job not found' by _assert_public_job when queue_service.is_public_job_async(job_id) returns False — the job id was never registered through the public build path. The static message is deliberate: reflecting the job_id or returning 403 would confirm which ids exist under other access tiers, leaking information about private builds.

Source

Thrown at src/backend/base/langflow/api/v1/chat.py:978

    return await get_flow_events_response(
        job_id=job_id,
        queue_service=queue_service,
        event_delivery=event_delivery,
    )


async def _assert_public_job(job_id: str, queue_service: JobQueueService) -> None:
    """Raise HTTP 404 if job_id was not registered through the public build endpoint.

    Prevents unauthenticated callers from reading or cancelling private-flow
    builds by guessing or leaking a job_id.

    Why 404 not 403: returning 403 would confirm the job exists under a different
    access tier, leaking information about private builds. 404 is neutral.
    """
    if not await queue_service.is_public_job_async(job_id):
        # Static detail — do not reflect job_id back; avoid confirming which IDs exist.
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Job not found")


@router.get("/build_public_tmp/{job_id}/events")
async def get_build_events_public(
    job_id: str,
    queue_service: Annotated[JobQueueService, Depends(get_queue_service)],
    *,
    event_delivery: EventDeliveryType = EventDeliveryType.STREAMING,
):
    """Get events for a public flow build job.

    This endpoint does not require authentication, matching the public build endpoint.
    It is used by the shareable playground to consume build events.
    """
    await _assert_public_job(job_id, queue_service)
    return await get_flow_events_response(
        job_id=job_id,
        queue_service=queue_service,

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Only use job ids returned by the public build endpoint itself, with public (share) flows.
  2. For authenticated builds, use the authenticated events/cancel endpoints, not the public ones.
  3. Open the events stream promptly after starting the public build so the marker is still live.
  4. Treat 404 as 'not a public job' — do not retry the same id; start a new public build instead.
Defensive patterns

Strategy: validation

Validate before calling

# Only call public endpoints with ids from the public build path
assert job_id.startswith("public-") or job_id in known_public_job_ids, "Not a public job"

Try / catch

try:
    res = await client.get(f"/api/v1/chat/build_public_tmp/{job_id}/events")
except httpx.HTTPStatusError as e:
    if e.response.status_code == 404:
        stop_polling(job_id)  # static detail; id is not a public job, do not retry
        return
    raise

Prevention

When it happens

Trigger: Hitting GET /build_public_tmp/{job_id}/events or the public cancel endpoint with: a private build's job_id, a guessed/random id, or a public job id whose marker expired in Redis.

Common situations: Attempting to read or cancel another user's build by replaying a leaked job_id; job marker TTL expiring before the events stream is opened; Redis flush removing public markers.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/7e5724584ae5ff06. Report an issue: GitHub.