amruthpillai/reactive-resume · warning · Error
Loading AI providers. Please try again in a moment.
Error message
Loading AI providers. Please try again in a moment.
What it means
Thrown synchronously inside the PDF import branch of the resume import dialog when useHasUsableAiProvider()'s isLoading flag is still true. The hook wraps orpc.aiProviders.list (a TanStack Query); isLoading is true before the first response arrives. This guard prevents calling client.ai.parsePdf before the provider list is known, because parsePdf needs a usable provider to exist. The thrown Error propagates to the onSubmit catch block which renders it as a toast.
Source
Thrown at apps/web/src/dialogs/resume/import.tsx:165
});
try {
let data: ResumeData | undefined;
if (value.type === "json-resume-json") {
data = parseJSONResume(await value.file.text());
}
if (value.type === "reactive-resume-json") {
data = parseReactiveResumeJSON(await value.file.text());
}
if (value.type === "reactive-resume-v4-json") {
data = parseReactiveResumeV4JSON(await value.file.text());
}
if (value.type === "pdf") {
if (isLoadingAiProviders) throw new Error(t`Loading AI providers. Please try again in a moment.`);
if (!hasUsableProvider)
throw new Error(t`This feature requires a connected AI provider. Please set one up in the settings.`);
const base64 = await fileToBase64(value.file);
data = await client.ai.parsePdf({
file: { name: value.file.name, data: base64 },
});
}
if (value.type === "docx") {
if (isLoadingAiProviders) throw new Error(t`Loading AI providers. Please try again in a moment.`);
if (!hasUsableProvider)
throw new Error(t`This feature requires a connected AI provider. Please set one up in the settings.`);
const base64 = await fileToBase64(value.file);
const mediaType =View on GitHub (pinned to 3a5b12e2a4)
Solutions
- Wait a moment and retry the import — this is a transient race that resolves once aiProviders.list settles.
- To prevent recurrence, also disable the Import button while providers are loading: add isLoadingAiProviders to the submit button's disabled condition (apps/web/src/dialogs/resume/import.tsx:428).
- If it persists, check the Network tab for the aiProviders.list request — a failing/CORS-blocked request leaves the query stuck loading; fix the backend/CORS config.
- Ensure the React Query client isn't being recreated on each render, which would reset query cache and reload providers every time.
Example fix
// before: submit disabled only when a provider is known-missing, not while loading
<Button type="submit" disabled={!type || !file || isImporting || (aiRequired && !hasUsableProvider)}>
// after: also block submit while AI providers are still loading
<Button
type="submit"
disabled={
!type || !file || isImporting || (aiRequired && (isLoadingAiProviders || !hasUsableProvider))
}
> Defensive patterns
Strategy: validation
Validate before calling
const { hasUsableProvider, isLoading } = useHasUsableAiProvider();
function canImportPdf(): boolean {
return !isLoading && hasUsableProvider;
}
// gate the submit: only call client.ai.parsePdf when canImportPdf() is true Type guard
function aiProvidersReady(isLoading: boolean, hasUsable: boolean): boolean {
return !isLoading && hasUsable;
} Try / catch
// onSubmit catch already toasts the message; to handle gracefully, pre-check:
if (isLoadingAiProviders) {
toast.info('Loading AI providers, please wait…');
return;
} Prevention
- Disable the Import button while isLoadingAiProviders is true (add it to the disabled prop).
- Prefetch orpc.aiProviders.list on the parent route so it is warm when the dialog opens.
- Do not recreate the React Query client per render.
When it happens
Trigger: User opens the import dialog, selects a PDF, and clicks Import during the brief window before the aiProviders.list query resolves on mount. Also possible if the query is stale/refetching after a network change and isLoading flips back. The submit button is supposed to be disabled when aiRequired && !hasUsableProvider, but that disable logic does not account for the loading state, so a fast click can slip through.
Common situations: Slow network or cold cache so the provider list query takes longer than the user's click. The query was unmounted/remounted (dialog re-opened) forcing a fresh fetch. React Query default staleTime causing a refetch on focus that briefly sets isLoading/isFetching. Race between the file-read and the provider-list fetch where the file finishes first.
Related errors
- This feature requires a connected AI provider. Please set on
- No data was returned from the AI provider.
- CONFLICT
- JSON.stringify(flattenError(error))
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/ad8a9a84cde1d5db.
Report an issue: GitHub.