{"record":{"id":"7a1727451cbd705d","repo":"langflow-ai/langflow","slug":"refusing-to-start-with-num-workers-workers-and-t","errorCode":null,"errorMessage":"Refusing to start with {num_workers} workers and the default in-memory job queue. POLLING and STREAMING event delivery fail with 'Job not found' roughly half the time because the build queue lives in one worker's memory and the follow-up GET /api/v1/build/<job_id>/events request lands on a different worker. Pick one of:\n  * Configure a shared job queue: LANGFLOW_JOB_QUEUE_TYPE=redis. Works for every event_delivery mode.\n  * Run with --workers 1. Single worker, no cross-worker routing.\nNote: event_delivery=direct works in multi-worker because the POST endpoint streams events back inline, but every client must opt into direct delivery; the server cannot enforce that at startup.","messagePattern":"Refusing to start with \\{num_workers\\} workers and the default in-memory job queue\\. POLLING and STREAMING event delivery fail with 'Job not found' roughly half the time because the build queue lives in one worker's memory and the follow-up GET /api/v1/build/<job_id>/events request lands on a different worker\\. Pick one of:\n  \\* Configure a shared job queue: LANGFLOW_JOB_QUEUE_TYPE=redis\\. Works for every event_delivery mode\\.\n  \\* Run with --workers 1\\. Single worker, no cross-worker routing\\.\nNote: event_delivery=direct works in multi-worker because the POST endpoint streams events back inline, but every client must opt into direct delivery; the server cannot enforce that at startup\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"src/backend/base/langflow/__main__.py","lineNumber":267,"sourceCode":"    \"\"\"\n    if num_workers <= 1:\n        return\n    if get_settings_service().settings.job_queue_type == \"redis\":\n        return\n    msg = (\n        f\"Refusing to start with {num_workers} workers and the default in-memory \"\n        \"job queue. POLLING and STREAMING event delivery fail with 'Job not found' \"\n        \"roughly half the time because the build queue lives in one worker's \"\n        \"memory and the follow-up GET /api/v1/build/<job_id>/events request lands \"\n        \"on a different worker. Pick one of:\\n\"\n        \"  * Configure a shared job queue: LANGFLOW_JOB_QUEUE_TYPE=redis. Works \"\n        \"for every event_delivery mode.\\n\"\n        \"  * Run with --workers 1. Single worker, no cross-worker routing.\\n\"\n        \"Note: event_delivery=direct works in multi-worker because the POST \"\n        \"endpoint streams events back inline, but every client must opt into \"\n        \"direct delivery; the server cannot enforce that at startup.\"\n    )\n    raise RuntimeError(msg)\n\n\ndef display_results(results) -> None:\n    \"\"\"Display the results of the migration.\"\"\"\n    for table_results in results:\n        table = Table(title=f\"Migration {table_results.table_name}\")\n        table.add_column(\"Name\")\n        table.add_column(\"Type\")\n        table.add_column(\"Status\")\n\n        for result in table_results.results:\n            status = \"Success\" if result.success else \"Failure\"\n            color = \"green\" if result.success else \"red\"\n            table.add_row(result.name, result.type, f\"[{color}]{status}[/{color}]\")\n\n        console.print(table)\n        console.print()  # Print a new line\n","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/__main__.py#L249-L285","documentation":"At startup, langflow run refuses (RuntimeError via ensure_multi_worker_safe) to launch with more than one worker while the default in-memory job queue is active. Build jobs would live in one worker's memory, and follow-up GET /api/v1/build/<job_id>/events requests would land on other workers, producing intermittent 'Job not found' failures for POLLING and STREAMING delivery. The fail-fast check replaces a heisenbug with a clear configuration error.","triggerScenarios":"langflow run --workers 4 (or LANGFLOW_WORKERS>1) without LANGFLOW_JOB_QUEUE_TYPE=redis; deploying multi-worker behind a load balancer with the default in-memory queue.","commonSituations":"Scaling up workers in production for CPU capacity; copying a single-worker dev config to a multi-worker container orchestration; setting workers via env var while forgetting the queue type.","solutions":["Configure a shared queue: set LANGFLOW_JOB_QUEUE_TYPE=redis (with a reachable Redis) — works for every event_delivery mode.","Or run single-worker: 'langflow run --workers 1'.","If all clients opt into event_delivery=direct, multi-worker is functionally safe, but the server still cannot verify client behavior — prefer one of the two supported configs above."],"exampleFix":"# before\nlangflow run --workers 4  # RuntimeError: Refusing to start with 4 workers and the default in-memory job queue\n# after (option A: shared queue)\nLANGFLOW_JOB_QUEUE_TYPE=redis langflow run --workers 4\n# after (option B: single worker)\nlangflow run --workers 1","handlingStrategy":"validation","validationCode":"import os\nworkers = int(os.environ.get(\"LANGFLOW_WORKERS\", \"1\"))\nqueue = os.environ.get(\"LANGFLOW_JOB_QUEUE_TYPE\", \"memory\")\nif workers > 1 and queue != \"redis\":\n    raise SystemExit(\"Set LANGFLOW_JOB_QUEUE_TYPE=redis or use --workers 1\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Codify the pairing in deployment config: workers>1 implies LANGFLOW_JOB_QUEUE_TYPE=redis plus a Redis URL.","Add a startup config lint in CI/compose so invalid combos never reach production.","Remember direct event_delivery only works if every client opts in — do not rely on it as the fix."],"tags":["startup","workers","job-queue","redis","configuration"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}