{"record":{"id":"cf741fc1678d5322","repo":"srbhr/Resume-Matcher","slug":"resume-tailoring-timed-out-after-settings-request","errorCode":null,"errorMessage":"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.","messagePattern":"Resume tailoring timed out after (.+?)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\\.","errorType":"http","errorClass":"HTTPException","httpStatus":504,"severity":"error","filePath":"apps/backend/app/routers/resumes.py","lineNumber":839,"sourceCode":"    try:\n        return await asyncio.wait_for(\n            _improve_preview_flow(\n                request=request,\n                resume=resume,\n                job=job,\n                language=language,\n                prompt_id=prompt_id,\n            ),\n            timeout=settings.request_timeout_seconds,\n        )\n    except asyncio.TimeoutError:\n        logger.error(\n            \"Improve preview timed out after %ss for resume %s / job %s\",\n            settings.request_timeout_seconds,\n            request.resume_id,\n            request.job_id,\n        )\n        raise HTTPException(\n            status_code=504,\n            detail=(\n                f\"Resume tailoring timed out after {settings.request_timeout_seconds}s. \"\n                \"If you are running a local LLM, raise REQUEST_TIMEOUT_SECONDS (and the \"\n                \"matching frontend NEXT_PUBLIC_REQUEST_TIMEOUT_MS); otherwise try a shorter \"\n                \"job description or a simpler prompt.\"\n            ),\n        )\n    except Exception as e:\n        _raise_improve_error(\"preview\", stage, e, detail)\n\n\nasync def _improve_preview_flow(\n    *,\n    request: ImproveResumeRequest,\n    resume: dict[str, Any],\n    job: dict[str, Any],\n    language: str,","sourceCodeStart":821,"sourceCodeEnd":857,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/resumes.py#L821-L857","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (.env backend)\nREQUEST_TIMEOUT_SECONDS=60\n// after\nREQUEST_TIMEOUT_SECONDS=300\n# plus frontend: NEXT_PUBLIC_REQUEST_TIMEOUT_MS=300000","handlingStrategy":"retry","validationCode":"function isLongJobDescription(jd: string, maxChars = 8000): boolean {\n  return jd.length <= maxChars; // trim long JDs client-side first\n}\nif (isLongJobDescription(jobDescription)) proceed(); else truncateOrSummarize(jobDescription);","typeGuard":"function hasSufficientTimeout(cfg: {REQUEST_TIMEOUT_SECONDS?: number}): boolean {\n  return typeof cfg.REQUEST_TIMEOUT_SECONDS === 'number' && cfg.REQUEST_TIMEOUT_SECONDS >= 120;\n}","tryCatchPattern":"async function previewWithRetry(payload: object, attempts = 2) {\n  try {\n    return await api.improvePreview(payload);\n  } catch (e) {\n    if (e.response?.status === 504 && attempts > 1) {\n      await sleep(2000);\n      return previewWithRetry(payload, attempts - 1);\n    }\n    if (e.response?.status === 504) showToast('Tailoring timed out — raise REQUEST_TIMEOUT_SECONDS or shorten the job description');\n    throw e;\n  }\n}","preventionTips":["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"],"tags":["timeout","http-504","llm","configuration","env-var"],"backgroundTag":"request-timeout-504","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}