{"record":{"id":"5b2d170b9048b8fe","repo":"srbhr/Resume-Matcher","slug":"request-timed-out-if-you-are-running-a-local-llm","errorCode":null,"errorMessage":"Request timed out. If you are running a local LLM, increase NEXT_PUBLIC_REQUEST_TIMEOUT_MS (and the backend REQUEST_TIMEOUT_SECONDS to match); otherwise try a shorter job description or check your connection.","messagePattern":"Request timed out\\. If you are running a local LLM, increase NEXT_PUBLIC_REQUEST_TIMEOUT_MS \\(and the backend REQUEST_TIMEOUT_SECONDS to match\\); otherwise try a shorter job description or check your connection\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/frontend/lib/api/client.ts","lineNumber":80,"sourceCode":"\n  if (isAbsoluteUrl) {\n    url = endpoint;\n  } else if (isApiPath) {\n    url = resolveRuntimeApiBase(normalizedEndpoint);\n  }\n\n  // Defaults to DEFAULT_TIMEOUT_MS, which tracks the backend's\n  // REQUEST_TIMEOUT_SECONDS (see next.config.ts proxyTimeout — all three layers\n  // must agree or the shortest aborts first).\n  const timeout = timeoutMs ?? DEFAULT_TIMEOUT_MS;\n  const controller = new AbortController();\n  const timer = setTimeout(() => controller.abort(), timeout);\n\n  try {\n    return await fetch(url, { ...options, signal: controller.signal });\n  } catch (error) {\n    if (error instanceof Error && error.name === 'AbortError') {\n      throw new Error(\n        'Request timed out. If you are running a local LLM, increase NEXT_PUBLIC_REQUEST_TIMEOUT_MS (and the backend REQUEST_TIMEOUT_SECONDS to match); otherwise try a shorter job description or check your connection.'\n      );\n    }\n    throw error;\n  } finally {\n    clearTimeout(timer);\n  }\n}\n\n/**\n * POST request with JSON body.\n */\nexport async function apiPost<T>(endpoint: string, body: T, timeoutMs?: number): Promise<Response> {\n  return apiFetch(\n    endpoint,\n    {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/frontend/lib/api/client.ts#L62-L98","documentation":"apiFetch wraps fetch with an AbortController timeout; when the request is aborted the browser throws an AbortError, which this code converts into a human-readable timeout Error. The message points at NEXT_PUBLIC_REQUEST_TIMEOUT_MS (frontend) and REQUEST_TIMEOUT_SECONDS (backend) as the knobs to tune.","triggerScenarios":"fetch to any API endpoint exceeds the configured timeout (default NEXT_PUBLIC_REQUEST_TIMEOUT_MS) and the controller aborts — e.g. long LLM generation on POST /analyze, slow local LLM, or stalled network connection.","commonSituations":"Running a local LLM (Ollama/llama.cpp) that takes minutes on a long job description while the frontend timeout defaults to ~30-60s; backend hanging on an upstream provider; VPN/proxy latency.","solutions":["Increase NEXT_PUBLIC_REQUEST_TIMEOUT_MS in the frontend env and REQUEST_TIMEOUT_SECONDS in the backend to a value exceeding worst-case LLM latency","Shorten the job description / reduce the workload sent to the LLM","Verify the backend is actually processing (check logs); if it is hung, fix the backend/LLM provider connectivity","Check network path (VPN, proxy) latency between frontend and backend"],"exampleFix":"// before (apps/frontend/.env.local)\nNEXT_PUBLIC_REQUEST_TIMEOUT_MS=30000\n// after\nNEXT_PUBLIC_REQUEST_TIMEOUT_MS=300000","handlingStrategy":"retry","validationCode":"const timeoutMs = Number(process.env.NEXT_PUBLIC_REQUEST_TIMEOUT_MS);\nif (!timeoutMs || timeoutMs < 60000) {\n  console.warn('NEXT_PUBLIC_REQUEST_TIMEOUT_MS too low for LLM workloads; set >= 120000');\n}","typeGuard":"function isTimeoutError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Request timed out');\n}","tryCatchPattern":"try {\n  return await apiPost('/analyze', body);\n} catch (e) {\n  if (isTimeoutError(e)) {\n    // retry once with backoff, or surface tuning hint\n    return await withBackoff(() => apiPost('/analyze', body), 1);\n  }\n  throw e;\n}","preventionTips":["Set NEXT_PUBLIC_REQUEST_TIMEOUT_MS above worst-case LLM latency and keep REQUEST_TIMEOUT_SECONDS in sync","Warn users before submitting very long job descriptions","Prefer streaming endpoints for long LLM jobs so no single request stalls","Alert on abort/timeout rates in the frontend to catch slow backends early"],"tags":["timeout","abort","network","fetch"],"backgroundTag":"request-timeout-abort","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}