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

  1. Fill in the model ID (the endpoint's exact model identifier) on the row indicated by the error index
  2. Remove the blank row if it was added accidentally
  3. 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

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


AI-assisted analysis of farion1231/cc-switch@a2e22f3302 (2026-08-16). Data as JSON: /api/errors/e76b8e8895aaf3f5. Report an issue: GitHub.