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
- No server fix needed — 499 here is informational; the job keeps running in the queue.
- On the client, raise the request timeout to exceed expected build time, or switch to streaming delivery.
- 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
- Set client timeouts longer than worst-case build time when polling.
- Prefer streaming delivery for long builds to avoid long-held polling requests.
- On disconnect, resume with the same job_id instead of restarting the build.
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.