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
- 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
- Use a faster/smaller LLM model or a hosted provider with lower latency
- Shorten the job description or use a simpler prompt preset
- 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
- Set REQUEST_TIMEOUT_SECONDS generously (>=120s) for local/slow LLMs and mirror it in NEXT_PUBLIC_REQUEST_TIMEOUT_MS
- Prefer a faster model or hosted provider for interactive tailoring
- Keep job descriptions under a few pages; summarize very long postings
- Warm up local models with a trivial request before the first real call
- Always change backend and frontend timeout values together
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Request timed out. If you are running a local LLM, increase
- Failed to test LLM connection (status ${res.status}).
- Resume preview data is invalid.
- LLM completion failed. Please check your API configuration a
- JSON extraction exceeded max recursion depth: {_depth}
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/cf741fc1678d5322.
Report an issue: GitHub.