farion1231/cc-switch · warning · PiFormValidationError
pi.form.thinkingLevelMapInvalid
Error message
pi.form.thinkingLevelMapInvalid
What it means
Thrown per-model in PiProviderForm's submit() when the row has a thinking-level map enabled (model.hasThinkingLevelMap) but its value fails isPiThinkingLevelMap (src/config/piThinkingProfiles.ts:347-355): the value must be a plain object whose keys are among 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' and whose values are strings or null. Arrays, unknown level keys, or numeric/boolean values fail. fieldSelector '#pi-model-thinking-levels-{model.key}' with revealAdvanced=true expands the row, opens the thinking map editor, and focuses it (PiProviderForm.tsx:1262-1277).
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 onlyView on GitHub (pinned to a2e22f3302)
Solutions
- Correct the map so every key is one of off/minimal/low/medium/high/xhigh/max and every value is a string or null
- If the row should not override thinking levels, remove the thinking map entirely instead of leaving an invalid one
- Validate with isPiThinkingLevelMap live as the user types and disable Save on failure
Example fix
// before
thinkingLevelMap: { high: 1, ultra: "model-x" }
// after
thinkingLevelMap: { high: "model-x-thinking", medium: null } Defensive patterns
Strategy: type-guard
Validate before calling
import { isPiThinkingLevelMap } from "@/config/piThinkingProfiles";
for (const m of models) {
if (m.hasThinkingLevelMap && !isPiThinkingLevelMap(m.thinkingLevelMap)) {
setFormError(t("pi.form.thinkingLevelMapInvalid"));
return;
}
} Type guard
import { isPiThinkingLevelMap } from "@/config/piThinkingProfiles";
// isPiThinkingLevelMap(value: unknown): value is PiThinkingLevelMap
// — plain object, keys in {off, minimal, low, medium, high, xhigh, max}, values string | null Try / catch
try {
await submit(identity);
} catch (error) {
if (error instanceof Error && error.name === "PiFormValidationError") { /* the form expands the row AND its thinking-map editor via '#pi-model-thinking-levels-{key}' */ return; }
throw error;
} Prevention
- Constrain the thinking-map editor to a dropdown of PI_THINKING_LEVELS instead of free JSON
- Run isPiThinkingLevelMap on every change and disable Save on failure
- Null is a valid value (level explicitly unset); numbers and unknown keys are not
When it happens
Trigger: Hand-editing the thinking map JSON with a typo'd level like 'ultra' or 'x-high'; using numbers ('high': 1) instead of model-name strings or null; leaving a JSON array or nested object in the field; importing a config with an off-spec thinking map.
Common situations: Copying thinking configs from other tools whose level names differ; assuming an empty object is fine for 'explicitly no mapping'; version drift when PI_THINKING_LEVELS gains/renames levels between releases.
Related errors
- jsonEditor.mustBeObject
- pi.form.selectPresetRequired
- pi.form.nameRequired
- pi.form.providerKeyRequired
- pi.form.credentialRequired
AI-assisted analysis of farion1231/cc-switch@a2e22f3302 (2026-08-16).
Data as JSON: /api/errors/138209de1a2f13cb.
Report an issue: GitHub.