srbhr/Resume-Matcher · error · HTTPException

Resume tailoring timed out after {settings.request_timeout_s

Error message

Resume tailoring timed out after {settings.request_timeout_seconds}s. If you are running a local LLM, raise REQUEST_TIMEOUT_SECONDS (and the matching frontend NEXT_PUBLIC_REQUEST_TIMEOUT_MS); otherwise try a shorter job description or a simpler prompt.

What it means

improve_resume_preview_endpoint raises HTTP 504 when the LLM tailoring call exceeds settings.request_timeout_seconds (via asyncio timeout). The message is tuned to point operators at the REQUEST_TIMEOUT_SECONDS env var and its frontend mirror NEXT_PUBLIC_REQUEST_TIMEOUT_MS.

Source

Thrown at apps/backend/app/routers/resumes.py:839

    try:
        return await asyncio.wait_for(
            _improve_preview_flow(
                request=request,
                resume=resume,
                job=job,
                language=language,
                prompt_id=prompt_id,
            ),
            timeout=settings.request_timeout_seconds,
        )
    except asyncio.TimeoutError:
        logger.error(
            "Improve preview timed out after %ss for resume %s / job %s",
            settings.request_timeout_seconds,
            request.resume_id,
            request.job_id,
        )
        raise HTTPException(
            status_code=504,
            detail=(
                f"Resume tailoring timed out after {settings.request_timeout_seconds}s. "
                "If you are running a local LLM, raise REQUEST_TIMEOUT_SECONDS (and the "
                "matching frontend NEXT_PUBLIC_REQUEST_TIMEOUT_MS); otherwise try a shorter "
                "job description or a simpler prompt."
            ),
        )
    except Exception as e:
        _raise_improve_error("preview", stage, e, detail)


async def _improve_preview_flow(
    *,
    request: ImproveResumeRequest,
    resume: dict[str, Any],
    job: dict[str, Any],
    language: str,

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Raise REQUEST_TIMEOUT_SECONDS in the backend env (e.g. to 300) and set the matching NEXT_PUBLIC_REQUEST_TIMEOUT_MS on the frontend, then restart
  2. Use a faster/smaller LLM model or a hosted provider with lower latency
  3. Shorten the job description or use a simpler prompt preset
  4. Pre-warm the local model (send a trivial request first) so the real request isn't penalized by cold-load time

Example fix

// before (.env backend)
REQUEST_TIMEOUT_SECONDS=60
// after
REQUEST_TIMEOUT_SECONDS=300
# plus frontend: NEXT_PUBLIC_REQUEST_TIMEOUT_MS=300000
Defensive patterns

Strategy: retry

Validate before calling

function isLongJobDescription(jd: string, maxChars = 8000): boolean {
  return jd.length <= maxChars; // trim long JDs client-side first
}
if (isLongJobDescription(jobDescription)) proceed(); else truncateOrSummarize(jobDescription);

Type guard

function hasSufficientTimeout(cfg: {REQUEST_TIMEOUT_SECONDS?: number}): boolean {
  return typeof cfg.REQUEST_TIMEOUT_SECONDS === 'number' && cfg.REQUEST_TIMEOUT_SECONDS >= 120;
}

Try / catch

async function previewWithRetry(payload: object, attempts = 2) {
  try {
    return await api.improvePreview(payload);
  } catch (e) {
    if (e.response?.status === 504 && attempts > 1) {
      await sleep(2000);
      return previewWithRetry(payload, attempts - 1);
    }
    if (e.response?.status === 504) showToast('Tailoring timed out — raise REQUEST_TIMEOUT_SECONDS or shorten the job description');
    throw e;
  }
}

Prevention

When it happens

Trigger: POST to improve/preview where the LLM stage takes longer than settings.request_timeout_seconds — large job descriptions, slow local Ollama/llama.cpp models, cold model loads, or long prompts.

Common situations: Self-hosting a quantized model on CPU-only hardware; first request after server start (model warm-up); very long job description pasted from a multi-page posting; default timeout too low for the chosen model/provider.

Understand the failure class

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/cf741fc1678d5322. Report an issue: GitHub.