{"record":{"id":"49e176e544033603","repo":"amruthpillai/reactive-resume","slug":"this-feature-requires-a-connected-ai-provider-ple","errorCode":null,"errorMessage":"This feature requires a connected AI provider. Please set one up in the settings.","messagePattern":"This feature requires a connected AI provider\\. Please set one up in the settings\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/web/src/dialogs/resume/import.tsx","lineNumber":167,"sourceCode":"\t\t\ttry {\n\t\t\t\tlet data: ResumeData | undefined;\n\n\t\t\t\tif (value.type === \"json-resume-json\") {\n\t\t\t\t\tdata = parseJSONResume(await value.file.text());\n\t\t\t\t}\n\n\t\t\t\tif (value.type === \"reactive-resume-json\") {\n\t\t\t\t\tdata = parseReactiveResumeJSON(await value.file.text());\n\t\t\t\t}\n\n\t\t\t\tif (value.type === \"reactive-resume-v4-json\") {\n\t\t\t\t\tdata = parseReactiveResumeV4JSON(await value.file.text());\n\t\t\t\t}\n\n\t\t\t\tif (value.type === \"pdf\") {\n\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\tdata = await client.ai.parsePdf({\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 (value.type === \"docx\") {\n\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)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/amruthpillai/reactive-resume/blob/3a5b12e2a40374a9571988701fcb75c5a1831c42/apps/web/src/dialogs/resume/import.tsx#L149-L185","documentation":"Thrown in the PDF import branch when isLoadingAiProviders is false but hasUsableProvider is false — meaning the provider list finished loading and no provider is both enabled AND testStatus==='success' (see useHasUsableAiProvider). PDF parsing requires a working AI provider on the server, so the client short-circuits before sending the file. The thrown Error is caught by onSubmit's catch and shown as a toast.","triggerScenarios":"User has zero AI providers configured and tries to import a PDF. User has providers configured but all are disabled. User has enabled providers but their connection test failed (testStatus !== 'success'), so none are 'usable'. The provider was just disconnected/deleted and the query has already refetched.","commonSituations":"Fresh install with no AI integration set up. An API key was entered but never passed the connection test. The provider's API key was revoked or the endpoint changed, so the stored testStatus is stale-failed. Environment variables for the AI provider are missing on the server so the connection test fails.","solutions":["Open Settings → Integrations and connect an AI provider (e.g. OpenAI-compatible endpoint) with a valid API key.","If a provider is already connected but failing, run its connection test from the Integrations page and ensure testStatus becomes 'success'.","Verify the required server-side environment variables / secrets for the chosen provider are set and that the server can reach the provider endpoint.","Once a usable provider exists, retry the PDF import."],"exampleFix":"// before: no usable provider, import attempted\n// user clicks Import with a PDF selected -> toast: 'requires a connected AI provider'\n\n// after: connect a provider, confirm test passes, then import\n// Settings -> Integrations -> add provider -> enter key -> test -> status 'success'\n// return to import dialog, select PDF, import succeeds","handlingStrategy":"validation","validationCode":"const { hasUsableProvider } = useHasUsableAiProvider();\nfunction canImportPdf(): boolean {\n  return hasUsableProvider;\n}\n// only enable the PDF/DOCX flow when canImportPdf() is true","typeGuard":"function hasUsableAi(providers: { enabled: boolean; testStatus: string }[]): boolean {\n  return providers.some((p) => p.enabled && p.testStatus === 'success');\n}","tryCatchPattern":"// the dialog already shows an inline 'Set up a provider' hint;\n// on submit, branch before throwing:\nif (!hasUsableProvider) {\n  // navigate to Integrations instead of throwing\n}","preventionTips":["Configure and connection-test at least one AI provider before offering PDF/DOCX import.","Show the 'Set up a provider' banner (already in the dialog) and keep the Import button disabled until hasUsableProvider is true.","Periodically re-test providers so testStatus stays accurate."],"tags":["ai-provider","import","configuration","ui"],"backgroundTag":null,"analyzedSha":"3a5b12e2a40374a9571988701fcb75c5a1831c42","analyzedAt":"2026-08-12T22:31:22.666Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}