{"record":{"id":"a7481c61791831ec","repo":"amruthpillai/reactive-resume","slug":"bad-request-a7481c","errorCode":"BAD_REQUEST","errorMessage":"No AI provider is configured. Add one in Settings → Integrations to use AI features.","messagePattern":"No AI provider is configured\\. Add one in Settings → Integrations to use AI features\\.","errorType":"http","errorClass":"ORPCError","httpStatus":400,"severity":"error","filePath":"packages/api/src/features/applications/ai.ts","lineNumber":40,"sourceCode":"const LINKEDIN_FETCH_RETRIES = 3;\ntype ValidatedAddress = { address: string; family: 4 | 6 };\n\ntype LinkedInJobPosting = {\n\ttitle: string;\n\tcompany: string | null;\n\tlocation: string | null;\n\tdescription: string | null;\n\tseniority: string | null;\n\temploymentType: string | null;\n\tjobFunction: string | null;\n\tindustries: string | null;\n};\n\n// Resolve the user's default (tested + enabled) AI provider into a ready model instance.\nasync function resolveModel(userId: string) {\n\tconst provider = await aiProvidersService.getDefaultRunnable({ userId });\n\tif (!provider) {\n\t\tthrow new ORPCError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"No AI provider is configured. Add one in Settings → Integrations to use AI features.\",\n\t\t});\n\t}\n\treturn getModel({\n\t\tprovider: provider.provider,\n\t\tmodel: provider.model,\n\t\tapiKey: provider.apiKey,\n\t\t...(provider.baseURL ? { baseURL: provider.baseURL } : {}),\n\t});\n}\n\n// generateText + tolerant JSON extraction + Zod validation. Mirrors the resume-analysis pattern\n// (the SDK's generateObject isn't wired for every provider here, so we parse defensively).\nasync function generateJson<T>(model: Awaited<ReturnType<typeof resolveModel>>, prompt: string, schema: z.ZodType<T>) {\n\tconst { text } = await generateText({ model, messages: [{ role: \"user\", content: prompt }] });\n\tconst fenced = text.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/);\n\tconst candidate = fenced?.[1] ?? text;\n\tconst start = candidate.indexOf(\"{\");","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/amruthpillai/reactive-resume/blob/3a5b12e2a40374a9571988701fcb75c5a1831c42/packages/api/src/features/applications/ai.ts#L22-L58","documentation":"BAD_REQUEST thrown by resolveModel in the applications AI module when aiProvidersService.getDefaultRunnable returns null — i.e. the user has no provider that is both enabled and testStatus 'success'. It is the applications-feature analogue of error 33, with a user-actionable message pointing to Settings → Integrations.","triggerScenarios":"Invoking any applications AI feature (e.g. job-posting analysis, cover-letter generation) while the user has zero enabled+tested providers. getDefaultRunnable queries for enabled=true AND testStatus='success' and returns null.","commonSituations":"New user who has not set up an AI provider; the user's provider was disabled or failed its test; all providers reset after a key/model/baseURL change; the user expects a system-wide default that does not exist.","solutions":["Guide the user to Settings → Integrations to add, test, and enable an AI provider.","On the client, detect the 'no provider' state and show a setup CTA before invoking the feature.","Ensure at least one provider has enabled=true and testStatus='success'.","After adding a provider, run the test and flip enabled on before retrying."],"exampleFix":"// before\nawait applications.analyzeJobPosting({ url }); // no provider set up\n\n// after\n// add + test + enable a provider first, then:\nawait applications.analyzeJobPosting({ url });","handlingStrategy":"validation","validationCode":"async function ensureApplicationsProvider(userId) {\n  const provider = await aiProvidersService.getDefaultRunnable({ userId });\n  if (!provider) throw new Error('setup required');\n  return provider;\n}","typeGuard":"function hasReadyProvider(list) {\n  return Array.isArray(list) && list.some(p => p.enabled && p.testStatus === 'success');\n}","tryCatchPattern":"try {\n  await applications.analyzeJobPosting({ url });\n} catch (e) {\n  if (e.code === 'BAD_REQUEST' && /No AI provider is configured/i.test(e.message)) {\n    routeTo('/settings/integrations');\n  } else throw e;\n}","preventionTips":["Detect 'no provider' state in the UI and show a setup CTA before invoking applications AI.","Ensure at least one provider is enabled and tested.","Re-test providers after any credential/config change."],"tags":["applications","ai","provider","onboarding","config","bad-request"],"backgroundTag":null,"analyzedSha":"3a5b12e2a40374a9571988701fcb75c5a1831c42","analyzedAt":"2026-08-12T22:31:22.666Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}