amruthpillai/reactive-resume · error · ORPCError
BAD_REQUEST
BAD_REQUEST
Error message
Invalid AI provider configuration.
What it means
Generic BAD_REQUEST thrown by the throwInvalidProviderConfig helper in the ai-providers router. It is reached when an underlying service call rejects with an Error whose message is exactly 'INVALID_AI_BASE_URL' (detected by isInvalidAiBaseUrl), meaning the supplied baseURL failed normalization/validation. The helper is shared by the create, update, and test handlers.
Source
Thrown at packages/api/src/features/ai-providers/router.ts:15
import type { AiProviderResponse } from "./service";
import { ORPCError } from "@orpc/client";
import { type } from "@orpc/server";
import z from "zod";
import { protectedProcedure } from "../../context";
import { aiRequestRateLimit } from "../../middleware/rate-limit";
import { providerInput, updateProviderInput } from "./inputs";
import { aiProvidersService } from "./service";
function isInvalidAiBaseUrl(error: unknown) {
return error instanceof Error && error.message === "INVALID_AI_BASE_URL";
}
function throwInvalidProviderConfig(): never {
throw new ORPCError("BAD_REQUEST", { message: "Invalid AI provider configuration." });
}
export const aiProvidersRouter = {
list: protectedProcedure
.route({
method: "GET",
path: "/ai-providers",
tags: ["AI Providers"],
operationId: "listAiProviders",
summary: "List saved AI providers",
description: "Lists saved provider/model/API key combinations for the authenticated user. API keys are redacted.",
})
.output(type<AiProviderResponse[]>())
.errors({
PRECONDITION_FAILED: { message: "AI agent workspace is not configured.", status: 412 },
})
.handler(({ context }) => aiProvidersService.list({ userId: context.user.id })),
View on GitHub (pinned to 3a5b12e2a4)
Solutions
- Provide a fully-qualified https:// baseURL with no trailing slash and no /v1 or /chat/completions suffix unless the provider requires it.
- Trim and validate the baseURL with new URL() on the client before submit.
- Check the provider's documented API base (e.g. https://api.openai.com/v1) and match the selected provider enum.
- For local/self-hosted gateways, confirm the host is reachable and serves the expected OpenAI-compatible schema.
Example fix
// before baseURL: 'openai.com/v1' // after baseURL: 'https://api.openai.com/v1'
Defensive patterns
Strategy: validation
Validate before calling
function validateBaseUrl(baseURL) {
if (!baseURL) return undefined;
const u = new URL(baseURL);
if (u.protocol !== 'http:' && u.protocol !== 'https:') throw new Error('INVALID_AI_BASE_URL');
return u.origin + (u.pathname.replace(/\/$/, ''));
} Type guard
function looksLikeValidAiBaseUrl(s) {
try { const u = new URL(s); return u.protocol === 'https:' && /^https:\/\//.test(s); } catch { return false; }
} Try / catch
try {
await createProvider(input);
} catch (e) {
if (e.code === 'BAD_REQUEST' && /Invalid AI provider configuration/i.test(e.message)) {
showFieldError('baseURL', 'Enter a full https:// URL for the provider.');
} else throw e;
} Prevention
- Validate baseURL with new URL() on the client before submit.
- Provide provider-specific baseURL presets to avoid typos.
- Strip trailing slashes and path suffixes the provider does not expect.
When it happens
Trigger: POST/PATCH /ai-providers or POST /ai-providers/{id}/test where the baseURL field is malformed (non-URL string, wrong scheme, unreachable host during normalization) causing the service to throw the sentinel 'INVALID_AI_BASE_URL' error, which the router remaps to this message.
Common situations: User enters a baseURL without the https:// scheme, with a trailing path that the provider rejects, with a typo, or pointing to a provider-specific endpoint path that is invalid for the chosen provider kind; copy-paste errors from docs that include extra quotes or whitespace.
Related errors
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/42ed57408576d5dd.
Report an issue: GitHub.