farion1231/cc-switch · warning · PiFormValidationError
Model {{index}} needs an ID
Error message
Model {{index}} needs an ID What it means
While normalizing the model list, PiProviderForm checks each row's id and throws pi.form.modelIdRequired (with 1-based index, focusing #pi-model-id-<rowKey> and revealing advanced fields) when model.id.length === 0. Unlike the name field, ids are deliberately NOT trimmed — the source comment notes Pi treats model ids as opaque strings — so an id of only whitespace still counts as non-empty, but an untouched empty row fails.
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 0b5da51016)
Solutions
- Fill the Model ID input of the row indicated by the {index} in the message (e.g. 'Model 2' = second row) with the exact id Pi/APIs expect, such as 'claude-sonnet-4'.
- Remove empty placeholder rows you did not intend to configure before submitting.
- When importing, skip or populate rows whose id is missing.
Example fix
// before
const models = [
{ key: "m1", id: "", name: "My model" }, // id never filled
];
submit(identity); // throws 'Model 1 needs an ID'
// after
const models = [
{ key: "m1", id: "gpt-5.2", name: "My model" },
];
submit(identity); Defensive patterns
Strategy: validation
Validate before calling
const emptyIdIndex = models.findIndex((m) => m.id.length === 0);
if (emptyIdIndex >= 0) focusRow(`#pi-model-id-${models[emptyIdIndex].key}`); Try / catch
catch (e) {
if (e instanceof PiFormValidationError) { setAdvancedOpen(e.revealAdvanced || advancedOpen); document.querySelector(e.fieldSelector ?? "")?.scrollIntoView({ block: "center" }); return; }
throw e;
} Prevention
- Validate each row's id on blur, not only at submit.
- Do not create model rows without ids in import code; filter them out first.
When it happens
Trigger: Clicking 'Add model' and saving without typing an id; deleting the id text of an auto-created empty row; importing models where one row's id is "".
Common situations: Users add a model row to see what it does, fill only the display name, and submit; a duplicate-check flow removed an id; keyboard focus loss leaves the id input blank.
Related errors
- Select a preset or custom configuration first
- Display name is required
- Provider key is required
- Add at least one model
- Model ID {{id}} is duplicated
AI-assisted analysis of farion1231/cc-switch@0b5da51016 (2026-08-20).
Data as JSON: /api/errors/6066f86312a5f968.
Report an issue: GitHub.