farion1231/cc-switch · error · PiFormValidationError
Model {{id}} needs an API, either directly or from the provi
Error message
Model {{id}} needs an API, either directly or from the provider What it means
PiProviderForm computes each model's transport: modelApi = trimmed passthrough api override (model.passthrough.api), falling back to the provider-level api field. In create mode it throws pi.form.effectiveApiRequired (with the model id, focusing #pi-provider-api-select, revealing advanced) when both are empty — the model would have no API type to route with. Edit mode is exempt because existing explicit nodes may be partial overrides of a Pi built-in provider that inherits the built-in transport.
Source
Thrown at src/components/providers/forms/PiProviderForm.tsx:1181
true,
);
}
// Pi's schema supports rare per-model api/baseUrl overrides. Keep
// imported values losslessly, but use the provider-level format and
// endpoint as the normal product model.
const modelApi =
typeof model.passthrough.api === "string"
? model.passthrough.api.trim()
: "";
const modelBaseUrl =
typeof model.passthrough.baseUrl === "string"
? model.passthrough.baseUrl.trim()
: "";
// Existing explicit nodes may be partial overrides of a Pi built-in
// provider. Pi inherits the built-in transport in that case, so only
// require a complete transport when CC Switch creates a new provider.
if (!isEdit && !modelApi && !api.trim()) {
throw new PiFormValidationError(
t("pi.form.effectiveApiRequired", { id }),
"#pi-provider-api-select",
true,
);
}
const effectiveUrl = modelBaseUrl || baseUrl.trim();
if (!isEdit && !effectiveUrl) {
throw new PiFormValidationError(
t("pi.form.effectiveBaseUrlRequired", { id }),
"#pi-provider-base-url",
);
}
return {
...model.passthrough,
id,
...(includeName ? { name: displayName } : {}),
...(includeReasoning ? { reasoning: model.reasoning } : {}),
...(includeInputView on GitHub (pinned to 0b5da51016)
Solutions
- Pick a value in the provider-level API selector (advanced section auto-reveals) such as 'anthropic' or 'openai', then resubmit.
- Alternatively give the specific model an api override in its passthrough settings if it must diverge from the provider default.
- If you were editing an existing provider and hit this, verify you did not accidentally open the create form with cleared transport state.
Example fix
// before
const api = ""; // provider API select left empty
const model = { id: "m1", passthrough: {} }; // no api override
submit(identity); // throws "Model m1 needs an API, ..."
// after
const api = "openai"; // set provider-level API type
submit(identity); Defensive patterns
Strategy: validation
Validate before calling
const modelApi = typeof model.passthrough.api === "string" ? model.passthrough.api.trim() : "";
if (!isEdit && !modelApi && !api.trim()) highlight("#pi-provider-api-select", "Choose the API type"); Type guard
const hasApiOverride = (m: ModelRow): boolean => typeof m.passthrough.api === "string" && m.passthrough.api.trim().length > 0;
Try / catch
catch (e) {
if (e instanceof PiFormValidationError && e.fieldSelector === "#pi-provider-api-select") { setAdvancedOpen(true); setFormError(e.message); return; }
throw e;
} Prevention
- Default the provider-level API select when a custom configuration is chosen.
- For imports, populate passthrough.api only with non-empty strings.
When it happens
Trigger: Creating a custom provider, choosing/entering models, but leaving the provider-level API select empty while no model carries a passthrough api; also when the api select was cleared after a preset switch to 'custom'.
Common situations: Custom (non-preset) configuration where the user assumes the API type is inferred from the base URL; importing models whose passthrough lacks 'api'; preset data lost during form state resets.
Related errors
- Model {{id}} needs a base URL, either directly or from the p
- {{label}} must be an absolute HTTP or HTTPS URL
- {{label}} must be a number greater than 0
- Select a preset or custom configuration first
- Configuration must be a JSON object, not an array or other t
AI-assisted analysis of farion1231/cc-switch@0b5da51016 (2026-08-20).
Data as JSON: /api/errors/a0a1eda4e445e103.
Report an issue: GitHub.