farion1231/cc-switch · warning · PiFormValidationError
Select a preset or custom configuration first
Error message
Select a preset or custom configuration first
What it means
PiProviderForm throws this PiFormValidationError when submit() runs in create mode (isEdit === false) and selectedPresetId is still null. The Pi provider form is preset-driven: a new provider must either clone a bundled preset or explicitly pick the 'custom' configuration before any other validation runs. It is the first gate in the submit() chain, so nothing else is validated until it passes.
Source
Thrown at src/components/providers/forms/PiProviderForm.tsx:1068
});
if (!applied) return;
includeCompatRef.current = includeCompat;
setProviderCompat(value);
},
[updateSettingsConfig],
);
const handleProviderKeyChange = useCallback((value: string) => {
const normalized = value.toLowerCase().replace(/[^a-z0-9-]/g, "");
setProviderKey(normalized);
}, []);
const submit = async (identity: ProviderFormData) => {
onSubmittingChange?.(true);
setFormError(null);
try {
if (!isEdit && selectedPresetId === null) {
throw new PiFormValidationError(t("pi.form.selectPresetRequired"));
}
if (!parseJsonObject(identity.settingsConfig)) {
throw new PiFormValidationError(
t("jsonEditor.mustBeObject"),
"#pi-settings-config",
);
}
const trimmedName = identity.name.trim();
const trimmedKey = providerKey.trim();
if (!trimmedName) {
throw new PiFormValidationError(
t("pi.form.nameRequired"),
'input[name="name"]',
);
}
if (!isEdit && !trimmedKey) {
throw new PiFormValidationError(
t("pi.form.providerKeyRequired"),View on GitHub (pinned to 0b5da51016)
Solutions
- In the create flow, choose a preset (or the 'custom configuration' option) so selectedPresetId becomes non-null, then resubmit.
- If you are driving the form programmatically, set the preset selection state before invoking submit().
- If users should be able to submit without a preset, pass an explicit 'custom' preset id instead of leaving selectedPresetId null.
Example fix
// before
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(null);
// user clicks submit -> throws 'Select a preset or custom configuration first'
// after
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(CUSTOM_PRESET_ID);
// or disable submit until a choice is made:
<button disabled={!isEdit && selectedPresetId === null}>Save</button> Defensive patterns
Strategy: validation
Validate before calling
const canSubmit = isEdit || selectedPresetId !== null;
// render: <button disabled={!canSubmit}>Save</button> Try / catch
try {
await submit(identity);
} catch (e) {
if (e instanceof PiFormValidationError) {
// e.fieldSelector is undefined here; prompt user to pick a preset
setFormError(e.message);
return;
}
throw e;
} Prevention
- Disable the submit button until a preset or the custom option is selected.
- Default selectedPresetId to 'custom' if your flow never needs the preset step.
When it happens
Trigger: Clicking the form's submit/confirm button in the 'Add provider' (create) flow without ever interacting with the preset selector, so selectedPresetId stays null. Only fires on create; editing an existing provider (isEdit) skips the check entirely.
Common situations: A UI regression or custom launcher invokes submit() before the preset step is completed; automation/tests call submit() directly on a fresh form; the preset picker was skipped because the dialog was opened in an unexpected state.
Related errors
- Configuration must be a JSON object, not an array or other t
- Display name is required
- Provider key is required
- Add at least one model
- Model {{index}} needs an ID
AI-assisted analysis of farion1231/cc-switch@0b5da51016 (2026-08-20).
Data as JSON: /api/errors/b0fd3ea854ccf697.
Report an issue: GitHub.