farion1231/cc-switch · warning · PiFormValidationError
pi.form.duplicateModel
Error message
pi.form.duplicateModel
What it means
Thrown per-model in PiProviderForm's submit() when two model rows share the exact same id string (PiProviderForm.tsx:1117-1124). Ids feed a Set ('seen') during normalization, and Pi's settings require unique model keys. Comparison is exact and case-sensitive: 'GPT' and 'gpt' are distinct and both pass. The message interpolates the duplicated id; fieldSelector '#pi-model-id-{model.key}' with revealAdvanced=true focuses the offending row.
Source
Thrown at src/components/providers/forms/PiProviderForm.tsx:1118
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;
const includeMaxTokens = !isEdit || model.hasMaxTokens;
if (includeName && !displayName) {
throw new PiFormValidationError(
t("pi.form.modelNameRequired", { index: index + 1 }),
`#pi-model-name-${model.key}`,
true,
);View on GitHub (pinned to a2e22f3302)
Solutions
- Rename or delete the duplicate row identified by the error message
- If two configs of one model are intended, give them distinct ids (for example a '-reasoning' suffix)
- Dedupe rows by id (case-sensitively) before enabling Save
Example fix
// before
const ids = models.map((m) => m.id);
// after (block duplicates before submit)
const ids = models.map((m) => m.id);
const hasDupes = new Set(ids).size !== ids.length;
<button type="submit" disabled={hasDupes}>Save</button>; Defensive patterns
Strategy: validation
Validate before calling
const seen = new Set<string>();
for (const [i, m] of models.entries()) {
if (seen.has(m.id)) {
setFormError(t("pi.form.duplicateModel", { id: m.id }));
return;
}
seen.add(m.id);
} Type guard
function hasUniqueModelIds(models: Array<{ id: string }>): boolean {
return new Set(models.map((m) => m.id)).size === models.length;
} Try / catch
try {
await submit(identity);
} catch (error) {
if (error instanceof Error && error.name === "PiFormValidationError") { /* message names the duplicated id; fieldSelector focuses that row */ return; }
throw error;
} Prevention
- Check duplicates case-sensitively — the backend Set is exact-match
- Warn inline as soon as a second row repeats an existing id
- When copying a row for a variant config, force an id suffix
When it happens
Trigger: Adding the same endpoint model twice; copy-pasting a row to tweak settings without changing its ID; importing a config that already contained a duplicate entry.
Common situations: User wants two configurations of one model (must differentiate ids); merged imports from two sources with overlapping model lists; accidental double-click on an add/import action.
Related errors
- pi.form.modelRequired
- pi.form.modelIdRequired
- pi.form.modelNameRequired
- pi.form.selectPresetRequired
- jsonEditor.mustBeObject
AI-assisted analysis of farion1231/cc-switch@a2e22f3302 (2026-08-16).
Data as JSON: /api/errors/347c308f37347dfc.
Report an issue: GitHub.