farion1231/cc-switch · warning · PiFormValidationError
pi.form.modelIdRequired
Error message
pi.form.modelIdRequired
What it means
Thrown per-model inside PiProviderForm's submit() normalization loop when a model row has an empty id (PiProviderForm.tsx:1109-1116). Pi treats model IDs as opaque strings that are NOT trimmed (comment at line 1112-1113: trimming would rename an imported model), so only a truly empty string fails. The message interpolates the 1-based row index; fieldSelector '#pi-model-id-{model.key}' plus revealAdvanced=true expands that row's details and focuses the ID input.
Source
Thrown at src/components/providers/forms/PiProviderForm.tsx:1111
"#pi-api-key",
);
}
if (!isEdit && models.length === 0) {
throw new PiFormValidationError(
t("pi.form.modelRequired"),
"#pi-add-model",
true,
);
}
const headers = normalizeRequestHeaders(providerHeaders);
const seen = new Set<string>();
const normalizedModels = models.map((model, index) => {
// Pi treats model IDs as opaque strings. Trimming would rename an
// imported model.
const id = model.id;
if (id.length === 0) {
throw new PiFormValidationError(
t("pi.form.modelIdRequired", { index: index + 1 }),
`#pi-model-id-${model.key}`,
true,
);
}
if (seen.has(id)) {
throw new PiFormValidationError(
t("pi.form.duplicateModel", { id }),
`#pi-model-id-${model.key}`,
true,
);
}
seen.add(id);
const displayName = model.name.trim();
const includeName = !isEdit || model.hasName;
const includeReasoning = !isEdit || model.hasReasoning;
const includeInput = !isEdit || model.hasInput;
const includeContextWindow = !isEdit || model.hasContextWindow;View on GitHub (pinned to a2e22f3302)
Solutions
- Fill in the model ID (the endpoint's exact model identifier) on the row indicated by the error index
- Remove the blank row if it was added accidentally
- Filter or block submission client-side when any row's id === ''
Example fix
// before
const rows = [{ id: "", name: "My model" }];
// after
const rows = [{ id: "gpt-5", name: "My model" }]; Defensive patterns
Strategy: validation
Validate before calling
const emptyRow = models.findIndex((m) => m.id === "");
if (emptyRow !== -1) {
setFormError(t("pi.form.modelIdRequired", { index: emptyRow + 1 }));
return;
} Type guard
const hasModelId = (m: { id: string }): boolean => m.id.length > 0; Try / catch
try {
await submit(identity);
} catch (error) {
if (error instanceof Error && error.name === "PiFormValidationError") { /* error.fieldSelector targets '#pi-model-id-{key}' and the form auto-expands that row */ return; }
throw error;
} Prevention
- Validate id !== '' per row as the user types and mark the row inline
- Offer a 'remove row' action that is easier than saving with blanks
- Do NOT trim ids before checking — Pi treats them as opaque strings
When it happens
Trigger: Adding a model row and saving without typing an ID; clearing the ID of a row imported from a preset; whitespace-only IDs DO pass (opaque strings), but the empty string does not.
Common situations: User fills display name but skips the machine ID; duplicate-UI where rows are added by button then left blank; importing provider JSON where a model entry lacked its id field.
Related errors
- pi.form.modelRequired
- pi.form.duplicateModel
- pi.form.modelNameRequired
- pi.form.selectPresetRequired
- jsonEditor.mustBeObject
AI-assisted analysis of farion1231/cc-switch@a2e22f3302 (2026-08-16).
Data as JSON: /api/errors/e76b8e8895aaf3f5.
Report an issue: GitHub.