{"record":{"id":"79e72647ab336a92","repo":"amruthpillai/reactive-resume","slug":"no-data-was-returned-from-the-ai-provider","errorCode":null,"errorMessage":"No data was returned from the AI provider.","messagePattern":"No data was returned from the AI provider\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/web/src/dialogs/resume/import.tsx","lineNumber":195,"sourceCode":"\t\t\t\t\tif (isLoadingAiProviders) throw new Error(t`Loading AI providers. Please try again in a moment.`);\n\t\t\t\t\tif (!hasUsableProvider)\n\t\t\t\t\t\tthrow new Error(t`This feature requires a connected AI provider. Please set one up in the settings.`);\n\n\t\t\t\t\tconst base64 = await fileToBase64(value.file);\n\n\t\t\t\t\tconst mediaType =\n\t\t\t\t\t\tvalue.file.type === \"application/msword\"\n\t\t\t\t\t\t\t? (\"application/msword\" as const)\n\t\t\t\t\t\t\t: (\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\" as const);\n\n\t\t\t\t\tdata = await client.ai.parseDocx({\n\t\t\t\t\t\tmediaType,\n\t\t\t\t\t\tfile: { name: value.file.name, data: base64 },\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!data) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tt({\n\t\t\t\t\t\t\tcomment: \"Error shown when AI import endpoint returns no parsed resume data\",\n\t\t\t\t\t\t\tmessage: \"No data was returned from the AI provider.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst id = await importResume({ data });\n\t\t\t\ttoast.success(t`Your resume has been imported successfully.`, { id: toastId, description: null });\n\t\t\t\tcloseDialog();\n\t\t\t\tvoid navigate({ to: \"/builder/$resumeId\", params: { resumeId: id } });\n\t\t\t} catch (error: unknown) {\n\t\t\t\ttoast.error(\n\t\t\t\t\tgetOrpcErrorMessage(error, {\n\t\t\t\t\t\tbyCode: {\n\t\t\t\t\t\t\tBAD_REQUEST: t({\n\t\t\t\t\t\t\t\tcomment: \"Error shown when AI parsing returns invalid resume structure during import\",\n\t\t\t\t\t\t\t\tmessage: \"The imported file could not be parsed into a valid resume.\",","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/amruthpillai/reactive-resume/blob/3a5b12e2a40374a9571988701fcb75c5a1831c42/apps/web/src/dialogs/resume/import.tsx#L177-L213","documentation":"Thrown after all import branches when the local `data` variable is still falsy. Per the inline comment this covers the case where the AI import endpoint returns no parsed resume data — i.e. client.ai.parsePdf/parseDocx resolved to undefined/null/empty. It also fires defensively if no type branch matched (though the form schema and the early return at line 141 normally prevent that). The thrown Error carries an i18n message comment ('Error shown when AI import endpoint returns no parsed resume data') and is shown as a toast.","triggerScenarios":"client.ai.parsePdf or client.ai.parseDocx resolves but returns undefined/null (the oRPC handler returned no payload). The AI provider responded but the server could not extract a valid resume structure and returned an empty result without throwing. A discriminated-union type mismatch where value.type doesn't match any branch (defensive fallback).","commonSituations":"The AI provider returned an empty or unparseable response (e.g. the PDF is image-only/scanned with no OCR-capable model). The server-side parser dropped the result due to a schema-validation failure that was swallowed. A model change or prompt regression causing the provider to return non-resume content. Rate-limiting/quota errors that the client surfaced as an empty response instead of an exception.","solutions":["Retry with a different file — the file may be image-only/scanned; use a text-based PDF or a DOCX with selectable text.","Switch to a more capable AI provider/model in Settings → Integrations and ensure its connection test passes.","Check server logs for the ai.parsePdf/parseDocx handler to see why it returned an empty payload (model error, truncated response, schema rejection).","If importing a JSON-based format, confirm the detected type matched (the Combobox) — a misdetected type can route to the wrong branch. As a workaround, manually pick 'JSON Resume' or 'Reactive Resume (JSON)'."],"exampleFix":"// before: scanned/image-only PDF -> AI returns no structured data\nconst data = await client.ai.parsePdf({ file: { name, data: base64 } });\n// data is undefined -> toast: 'No data was returned from the AI provider.'\n\n// after: use a text-based source or a stronger model\n// 1. Re-export the resume to a text PDF / DOCX with selectable text, or\n// 2. Switch to an OCR-capable / stronger provider in Integrations, then retry.","handlingStrategy":"try-catch","validationCode":"// validate the file has extractable text before sending to AI\nasync function hasSelectableText(file: File): Promise<boolean> {\n  if (file.type === 'application/pdf') {\n    // heuristic: very small text layer -> likely scanned\n    return file.size > 0; // full text-check needs a PDF lib; at minimum warn on tiny files\n  }\n  return true;\n}\nif (!(await hasSelectableText(file))) {\n  warnUser('This file looks scanned; AI may return no data.');\n}","typeGuard":"function hasAiData<T>(data: T | undefined | null): data is T {\n  return data != null;\n}","tryCatchPattern":"let data = await client.ai.parsePdf({ file });\nif (!data) {\n  // show actionable message: try a text-based file or a different provider\n  toast.error('No data returned. Try a text-based PDF or switch AI provider.');\n  return;\n}","preventionTips":["Prefer text-based PDFs/DOCX (selectable text) over scanned images.","Use an OCR-capable or stronger model if scanned input is expected.","Confirm the detected import type matches the file before submit.","Log server-side parse results to catch empty-response regressions early."],"tags":["ai-provider","import","pdf","docx","empty-response"],"backgroundTag":null,"analyzedSha":"3a5b12e2a40374a9571988701fcb75c5a1831c42","analyzedAt":"2026-08-12T22:31:22.666Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}