bytedance/deer-flow · error · HTTPException

Failed to polish input

Error message

Failed to polish input

What it means

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.

Source

Thrown at backend/app/gateway/routers/input_polish.py:99

    max_chars = config.input_polish.max_chars
    if len(text) > max_chars:
        raise HTTPException(status_code=400, detail=f"Input text exceeds {max_chars} characters")

    model_name = config.input_polish.model_name
    try:
        raw = await run_oneshot_llm(
            system_instruction=_build_system_instruction(),
            user_content=_build_user_content(text, body.locale),
            run_name="input_polish",
            app_config=config,
            model_name=model_name,
            thread_id=body.thread_id,
        )
        rewritten = _clean_rewritten_text(raw)
    except Exception as exc:
        logger.exception("Failed to polish input: thread_id=%s err=%s", body.thread_id, exc)
        raise HTTPException(status_code=503, detail="Failed to polish input") from exc

    if not rewritten:
        raise HTTPException(status_code=503, detail="Failed to polish input")

    return InputPolishResponse(
        rewritten_text=rewritten,
        changed=rewritten != text,
    )

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Check Gateway logs for the chained exception — it names the actual provider error.
  2. Verify LLM credentials and that config.input_polish.model_name is a valid, accessible model.
  3. Retry with backoff (503 is transient), and degrade gracefully by sending the draft unpolished if retry fails.

Example fix

// before
const res = await polish({ text });
const { rewritten_text } = await res.json();

// after
for (let i = 0; i < 3; i++) {
  const res = await polish({ text });
  if (res.ok) return (await res.json()).rewritten_text;
  if (res.status !== 503) break;
  await sleep(2 ** i * 500);
}
return text; // fallback: send draft unpolished
Defensive patterns

Strategy: retry

Try / catch

for (let i = 0; i < 3; i++) {
  try { return await polishOnce(text); }
  catch (e) { if (e.status !== 503 || i === 2) return text; /* fallback: unpolished */ await sleep(2 ** i * 500); }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/24b894e0fe06d11b. Report an issue: GitHub.