{"record":{"id":"699bf11101e8ba5b","repo":"headroomlabs-ai/headroom","slug":"workers-must-be-1","errorCode":null,"errorMessage":"workers must be >= 1","messagePattern":"workers must be >= 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/proxy/server.py","lineNumber":5263,"sourceCode":"            still gets the banner since it has no other startup output.\n    \"\"\"\n    if not FASTAPI_AVAILABLE:\n        print(\"ERROR: FastAPI required. Install: pip install fastapi uvicorn httpx\")\n        sys.exit(1)\n\n    # Seed the request-time coding-profile toggles (tool-search, dedupe, read\n    # protection, lossless→lossy, effort-router, block-char floor) into the\n    # process env before serving, so downstream per-request readers pick them up.\n    # Done here (not in the CLI command) so unit tests that mock run_server never\n    # mutate os.environ. setdefault → explicit env still wins. MODE / profile are\n    # already resolved into `config` above via their inline defaults.\n    from headroom.agent_savings import seed_proxy_env_defaults\n\n    seed_proxy_env_defaults()\n\n    config = config or ProxyConfig()\n    if workers < 1:\n        raise ValueError(\"workers must be >= 1\")\n    config.worker_processes = workers\n    code_aware_status = _get_code_aware_banner_status(config)\n\n    # Format connection pool info\n    pool_info = f\"max={config.max_connections}, keepalive={config.max_keepalive_connections}\"\n    http2_status = \"ENABLED\" if (config.http2 and not config.http_proxy) else \"DISABLED\"\n\n    backend_status = format_backend_status(\n        backend=config.backend,\n        anyllm_provider=config.anyllm_provider,\n        bedrock_region=config.bedrock_region,\n    )\n\n    # Resolve upstream API targets for display in the banner (#583).\n    api_targets = resolve_api_targets(config.provider_api_overrides)\n\n    if print_banner:\n        print(f\"\"\"","sourceCodeStart":5245,"sourceCodeEnd":5281,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/proxy/server.py#L5245-L5281","documentation":"run_server validates that the worker process count is at least 1; workers < 1 (0 or negative) is rejected with ValueError before configuration is finalized. Worker count maps onto ProxyConfig.worker_processes, which itself must be >= 1.","triggerScenarios":"Calling run_server(workers=0) or run_server(workers=-1); computing workers from an expression like len(tasks)-1 that can go negative; CLI flags accepting 0.","commonSituations":"Auto-sizing workers from CPU/load formulas that return 0; passing a CLI --workers 0 expecting single-process mode; config templating with an unset variable defaulting to 0.","solutions":["Pass workers=1 for single-process serving.","Clamp computed worker counts with max(1, computed).","Validate CLI/env worker inputs to IntRange(min=1)-style bounds."],"exampleFix":"# before\nrun_server(config=config, workers=max(0, os.cpu_count() - 8))\n\n# after\nrun_server(config=config, workers=max(1, os.cpu_count() - 8))","handlingStrategy":"validation","validationCode":"workers = max(1, int(os.environ.get(\"HEADROOM_WORKERS\", \"1\")))\nif workers < 1:\n    raise SystemExit(\"workers must be >= 1\")","typeGuard":"def valid_workers(n: int) -> bool:\n    return isinstance(n, int) and n >= 1","tryCatchPattern":"try:\n    run_server(config=config, workers=workers)\nexcept ValueError as e:\n    if \"workers\" in str(e):\n        run_server(config=config, workers=1)\n    else:\n        raise","preventionTips":["Clamp auto-computed worker counts with max(1, n).","Use 1 for single-process; never 0."],"tags":["config","validation","server"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}