langflow-ai/langflow · info · HTTPException

Event polling was cancelled

Error message

Event polling was cancelled

What it means

Raised when the polling loop for build events is cancelled via asyncio.CancelledError — almost always because the HTTP client disconnected while the server was waiting for the next event batch. It is mapped to status 499 (nginx-style 'client closed request') and logged at info level, confirming it is an expected lifecycle event, not a fault.

Source

Thrown at src/backend/base/langflow/api/build.py:315

                events.append(_project_event_to_v1(value.decode("utf-8")))

            # If no events were available, wait for one (with timeout)
            if not events:
                _, value, _ = await main_queue.get()
                if value is None:
                    # End of stream, trigger end event
                    if event_task is not None:
                        event_task.cancel()
                    event_manager.on_end(data={})
                else:
                    events.append(_project_event_to_v1(value.decode("utf-8")))

            # Return as NDJSON format - each line is a complete JSON object
            content = "\n".join([event for event in events if event is not None])
            return Response(content=content, media_type="application/x-ndjson")
        except asyncio.CancelledError as exc:
            await logger.ainfo(f"Event polling was cancelled for job {job_id}")
            raise HTTPException(status_code=499, detail="Event polling was cancelled") from exc
        except asyncio.TimeoutError:
            await logger.awarning(f"Timeout while waiting for events for job {job_id}")
            return Response(content="", media_type="application/x-ndjson")  # Return empty response instead of error

    except JobQueueNotFoundError as exc:
        await logger.aerror(f"Job not found: {job_id}. Error: {exc!s}")
        raise HTTPException(status_code=404, detail=f"Job not found: {exc!s}") from exc
    except Exception as exc:
        if isinstance(exc, HTTPException):
            raise
        await logger.aexception(f"Unexpected error processing flow events for job {job_id}")
        raise HTTPException(status_code=500, detail=f"Unexpected error: {exc!s}") from exc


async def create_flow_response(
    queue: asyncio.Queue,
    event_manager: EventManager,
    event_task: asyncio.Task | None,

View on GitHub (pinned to 976ec789d2)

Solutions

  1. No server fix needed — 499 here is informational; the job keeps running in the queue.
  2. On the client, raise the request timeout to exceed expected build time, or switch to streaming delivery.
  3. Re-attach with the same job_id to resume consuming events instead of restarting the build.

Example fix

// before (client aborts early)
const res = await fetch(url, { signal: AbortSignal.timeout(2000) });

// after
const res = await fetch(url, { signal: AbortSignal.timeout(300_000) });
Defensive patterns

Strategy: fallback

Try / catch

try:
    events = await poll_events(job_id)
except HTTPError as e:
    if e.response.status_code == 499:
        events = await poll_events(job_id)  # job still runs; just re-attach
    else:
        raise

Prevention

When it happens

Trigger: Using event_delivery=polling on the events endpoint and the client (browser tab closed, curl interrupted, SDK timeout) drops the connection before the stream ends; server shutdown cancelling the handler task.

Common situations: Frontend StrictMode double-mounts aborting the first poll; aggressive client timeouts shorter than the build duration; users navigating away mid-build.


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