{"record":{"id":"412a0ca228605630","repo":"bytedance/deer-flow","slug":"mcp-task-service-not-available","errorCode":null,"errorMessage":"MCP task service not available","messagePattern":"MCP task service not available","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"backend/app/gateway/deps.py","lineNumber":675,"sourceCode":"\ndef get_scheduled_task_service(request: Request):\n    val = getattr(request.app.state, \"scheduled_task_service\", None)\n    if val is None:\n        raise HTTPException(status_code=503, detail=\"Scheduled task service not available\")\n    return val\n\n\ndef get_mcp_task_repo(request: Request):\n    val = getattr(request.app.state, \"mcp_task_repo\", None)\n    if val is None:\n        raise HTTPException(status_code=503, detail=\"MCP task repo not available\")\n    return val\n\n\ndef get_mcp_task_service(request: Request):\n    val = getattr(request.app.state, \"mcp_task_service\", None)\n    if val is None:\n        raise HTTPException(status_code=503, detail=\"MCP task service not available\")\n    return val\n\n\ndef get_run_context(request: Request) -> RunContext:\n    \"\"\"Build a :class:`RunContext` from ``app.state`` singletons.\n\n    Returns a *base* context with infrastructure dependencies. The\n    ``app_config`` field is resolved live so per-run fields (e.g.\n    ``models[*].max_tokens``) follow ``config.yaml`` edits; the\n    ``event_store`` / ``run_events_config`` pair stays frozen to the snapshot\n    captured in :func:`langgraph_runtime` so callers never see a store bound\n    to one backend paired with a config pointing at another.\n    \"\"\"\n    return RunContext(\n        checkpointer=get_checkpointer(request),\n        store=get_store(request),\n        event_store=get_run_event_store(request),\n        run_events_config=getattr(request.app.state, \"run_events_config\", None),","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/deps.py#L657-L693","documentation":"HTTP 503 from get_mcp_task_service() when app.state.mcp_task_service is None. The MCP task service coordinates task lifecycle operations on top of mcp_task_repo; missing means MCP task subsystem bootstrap did not complete.","triggerScenarios":"Any route depending on get_mcp_task_service when the service was never constructed during lifespan — usually the same root cause as the missing repo (persistence failure) one layer up.","commonSituations":"Same as MCP task repo: DB down at startup, incomplete migrations, or tests mounting routers without lifespan; occasionally the service fails alone because of a malformed MCP extension config.","solutions":["Resolve the underlying init failure shown in Gateway startup logs (persistence/migrations first)","Confirm mcp_task_repo is also healthy — the service depends on it","Restart the Gateway; both singletons are restart-required and only re-attach at lifespan"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    result = await api.run_mcp_task_action(task_id, action)\nexcept HTTP503 as e:\n    if 'MCP task service' in e.detail:\n        show_feature_unavailable_banner()\n        return\n    raise","preventionTips":["If the repo getter 503s, assume the service will too — fail fast without hammering both","Keep MCP extension config valid; service construction can fail on malformed MCP config","Alert on any 'not available' 503 pattern — it always means a startup defect, not a transient error"],"tags":["http-503","mcp","service","persistence","gateway"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}