{"record":{"id":"24b894e0fe06d11b","repo":"bytedance/deer-flow","slug":"failed-to-polish-input","errorCode":null,"errorMessage":"Failed to polish input","messagePattern":"Failed to polish input","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"backend/app/gateway/routers/input_polish.py","lineNumber":99,"sourceCode":"\n    max_chars = config.input_polish.max_chars\n    if len(text) > max_chars:\n        raise HTTPException(status_code=400, detail=f\"Input text exceeds {max_chars} characters\")\n\n    model_name = config.input_polish.model_name\n    try:\n        raw = await run_oneshot_llm(\n            system_instruction=_build_system_instruction(),\n            user_content=_build_user_content(text, body.locale),\n            run_name=\"input_polish\",\n            app_config=config,\n            model_name=model_name,\n            thread_id=body.thread_id,\n        )\n        rewritten = _clean_rewritten_text(raw)\n    except Exception as exc:\n        logger.exception(\"Failed to polish input: thread_id=%s err=%s\", body.thread_id, exc)\n        raise HTTPException(status_code=503, detail=\"Failed to polish input\") from exc\n\n    if not rewritten:\n        raise HTTPException(status_code=503, detail=\"Failed to polish input\")\n\n    return InputPolishResponse(\n        rewritten_text=rewritten,\n        changed=rewritten != text,\n    )\n","sourceCodeStart":81,"sourceCodeEnd":108,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/input_polish.py#L81-L108","documentation":"Raised by POST /input-polish with status 503 when run_oneshot_llm (or the result cleanup) raises any exception — the underlying one-shot LLM call failed. The original exception is logged with traceback ('Failed to polish input: thread_id=... err=...') and chained; 503 signals a transient upstream dependency failure so clients may retry.","triggerScenarios":"LLM provider outage, rate limit, or auth failure; invalid/missing model config for input_polish.model_name; network egress blocked from the Gateway to the provider; token/context errors from the provider.","commonSituations":"Expired or wrong LLM API key; input_polish.model_name pointing to a model the account can't access; provider 429s during peak traffic; DNS/proxy issues in containerized deployments.","solutions":["Check Gateway logs for the chained exception — it names the actual provider error.","Verify LLM credentials and that config.input_polish.model_name is a valid, accessible model.","Retry with backoff (503 is transient), and degrade gracefully by sending the draft unpolished if retry fails."],"exampleFix":"// before\nconst res = await polish({ text });\nconst { rewritten_text } = await res.json();\n\n// after\nfor (let i = 0; i < 3; i++) {\n  const res = await polish({ text });\n  if (res.ok) return (await res.json()).rewritten_text;\n  if (res.status !== 503) break;\n  await sleep(2 ** i * 500);\n}\nreturn text; // fallback: send draft unpolished","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let i = 0; i < 3; i++) {\n  try { return await polishOnce(text); }\n  catch (e) { if (e.status !== 503 || i === 2) return text; /* fallback: unpolished */ await sleep(2 ** i * 500); }\n}","preventionTips":["Verify LLM credentials and input_polish.model_name in config","Treat 503 as transient — retry with exponential backoff","Always fall back to sending the raw draft if polish fails"],"tags":["http-503","llm","upstream-failure","input-polish","retryable"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}