farion1231/cc-switch · error · PiFormValidationError

Thinking levels may only use Pi's native keys, with string o

Error message

Thinking levels may only use Pi's native keys, with string or null values.

What it means

PiProviderForm validates the per-model thinking-level map with isPiThinkingLevelMap() when the row carries one (model.hasThinkingLevelMap); on failure it throws pi.form.thinkingLevelMapInvalid focusing #pi-model-thinking-levels-<rowKey> with revealAdvanced. Pi's native schema only accepts its own thinking-level keys mapped to string or null values (e.g. levels like 'high'/'medium'/'off' style names), so free-form objects, numbers, booleans, or arrays are rejected to keep the generated settings file schema-valid.

Source

Thrown at src/components/providers/forms/PiProviderForm.tsx:1160

                label: t("pi.form.contextWindow"),
              }),
              `#pi-model-context-window-${model.key}`,
            )
          : undefined;
        const maxTokens = includeMaxTokens
          ? positiveNumber(
              model.maxTokens,
              t("pi.form.positiveNumberRequired", {
                label: t("pi.form.maxTokens"),
              }),
              `#pi-model-max-tokens-${model.key}`,
            )
          : undefined;
        if (
          model.hasThinkingLevelMap &&
          !isPiThinkingLevelMap(model.thinkingLevelMap)
        ) {
          throw new PiFormValidationError(
            t("pi.form.thinkingLevelMapInvalid"),
            `#pi-model-thinking-levels-${model.key}`,
            true,
          );
        }
        // Pi's schema supports rare per-model api/baseUrl overrides. Keep
        // imported values losslessly, but use the provider-level format and
        // endpoint as the normal product model.
        const modelApi =
          typeof model.passthrough.api === "string"
            ? model.passthrough.api.trim()
            : "";
        const modelBaseUrl =
          typeof model.passthrough.baseUrl === "string"
            ? model.passthrough.baseUrl.trim()
            : "";
        // Existing explicit nodes may be partial overrides of a Pi built-in
        // provider. Pi inherits the built-in transport in that case, so only

View on GitHub (pinned to 0b5da51016)

Solutions

  1. Rewrite the map to use Pi's native thinking-level keys with string or null values, e.g. { "default": "high", "off": null }-shaped entries per Pi's documented schema.
  2. Remove the thinking-level override entirely if you do not need it — the field is optional (hasThinkingLevelMap false rows skip validation).
  3. Check Pi's provider schema/docs for the exact allowed key set for your provider version before hand-writing the map.

Example fix

// before
thinkingLevelMap = { high: 3, medium: 2 }; // numeric values -> throws
// or
thinkingLevelMap = { "deep-think": "on" }; // non-native key -> throws

// after
thinkingLevelMap = { high: "high", medium: "medium", low: null }; // string|null values on native keys
Defensive patterns

Strategy: type-guard

Validate before calling

import { isPiThinkingLevelMap } from "./piSchema"; // same helper the form uses
if (model.hasThinkingLevelMap && !isPiThinkingLevelMap(model.thinkingLevelMap)) {
  showEditorError("Thinking levels: native keys only, string or null values");
}

Type guard

function isPiThinkingLevelMap(v: unknown): v is Record<string, string | null> {
  if (typeof v !== "object" || v === null || Array.isArray(v)) return false;
  return Object.values(v).every((x) => x === null || typeof x === "string");
}

Try / catch

catch (e) {
  if (e instanceof PiFormValidationError) { setAdvancedOpen(true); setFormError(e.message); return; }
  throw e;
}

Prevention

When it happens

Trigger: Hand-editing the thinking levels JSON to use non-native keys (custom names like "deep-think"), values of wrong type (0/1/2, true, nested objects), or pasting a generic reasoning-effort config from another tool; only checked when the row actually has a thinkingLevelMap.

Common situations: Porting OpenAI-style reasoning_effort numbers or Anthropic budget_tokens into Pi's thinking map; typos in level keys; mixing formats when copying configs between providers.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of farion1231/cc-switch@0b5da51016 (2026-08-20). Data as JSON: /api/errors/7a9dbb490a32620f. Report an issue: GitHub.