{"record":{"id":"91973c8ec864c45d","repo":"farion1231/cc-switch","slug":"pi-form-effectiveapirequired","errorCode":null,"errorMessage":"pi.form.effectiveApiRequired","messagePattern":"pi\\.form\\.effectiveApiRequired","errorType":"validation","errorClass":"PiFormValidationError","httpStatus":null,"severity":"warning","filePath":"src/components/providers/forms/PiProviderForm.tsx","lineNumber":1181,"sourceCode":"            true,\n          );\n        }\n        // Pi's schema supports rare per-model api/baseUrl overrides. Keep\n        // imported values losslessly, but use the provider-level format and\n        // endpoint as the normal product model.\n        const modelApi =\n          typeof model.passthrough.api === \"string\"\n            ? model.passthrough.api.trim()\n            : \"\";\n        const modelBaseUrl =\n          typeof model.passthrough.baseUrl === \"string\"\n            ? model.passthrough.baseUrl.trim()\n            : \"\";\n        // Existing explicit nodes may be partial overrides of a Pi built-in\n        // provider. Pi inherits the built-in transport in that case, so only\n        // require a complete transport when CC Switch creates a new provider.\n        if (!isEdit && !modelApi && !api.trim()) {\n          throw new PiFormValidationError(\n            t(\"pi.form.effectiveApiRequired\", { id }),\n            \"#pi-provider-api-select\",\n            true,\n          );\n        }\n        const effectiveUrl = modelBaseUrl || baseUrl.trim();\n        if (!isEdit && !effectiveUrl) {\n          throw new PiFormValidationError(\n            t(\"pi.form.effectiveBaseUrlRequired\", { id }),\n            \"#pi-provider-base-url\",\n          );\n        }\n        return {\n          ...model.passthrough,\n          id,\n          ...(includeName ? { name: displayName } : {}),\n          ...(includeReasoning ? { reasoning: model.reasoning } : {}),\n          ...(includeInput","sourceCodeStart":1163,"sourceCodeEnd":1199,"githubUrl":"https://github.com/farion1231/cc-switch/blob/a2e22f330273a5b6ffa87cb8b82b624601bac562/src/components/providers/forms/PiProviderForm.tsx#L1163-L1199","documentation":"Thrown per-model in PiProviderForm's submit() when creating (!isEdit) with neither a per-model passthrough 'api' override (model.passthrough.api) nor a provider-level api selected (PiProviderForm.tsx:1174-1180). Pi needs a wire format (API family) to talk to the endpoint. Edit mode is exempt by design: existing explicit nodes may be partial overrides of a Pi built-in provider and inherit its transport (comment at lines 1170-1173). The message interpolates the model id; fieldSelector '#pi-provider-api-select' with revealAdvanced=true focuses the API selector.","triggerScenarios":"Creating a provider, leaving the API protocol dropdown empty, and not setting 'api' in any model's advanced passthrough JSON; selecting 'Custom' preset which does not prefill an api format.","commonSituations":"User assumes baseUrl alone is enough; preset template lacked an api value; per-model overrides were cleared during import; user confusion between the provider-level selector and the per-model passthrough field.","solutions":["Pick the API format (e.g. the OpenAI- or Anthropic-compatible family) in the provider's advanced/API settings, then save","Alternatively set a per-model passthrough \"api\" string in the model's advanced JSON","When building custom flows, default api from the selected preset's template values"],"exampleFix":"// before\nconst values = { /* ... */ api: \"\" };\n\n// after\nconst values = { /* ... */ api: \"openai\" }; // or \"anthantic\"-family per your endpoint; must match a known Pi api format","handlingStrategy":"validation","validationCode":"const modelApi = typeof model.passthrough.api === \"string\" ? model.passthrough.api.trim() : \"\";\nif (!isEdit && !modelApi && api.trim() === \"\") {\n  setFormError(t(\"pi.form.effectiveApiRequired\", { id: model.id }));\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await submit(identity);\n} catch (error) {\n  if (error instanceof Error && error.name === \"PiFormValidationError\") { /* focuses '#pi-provider-api-select' after revealing advanced settings */ return; }\n  throw error;\n}","preventionTips":["Default the api format from the selected preset's templateValues","Disable Save in create mode until api is chosen or a per-model passthrough api exists","Remember edit mode is exempt: partial overrides inherit the built-in provider's transport"],"tags":["form-validation","pi","api-format","transport"],"backgroundTag":null,"analyzedSha":"a2e22f330273a5b6ffa87cb8b82b624601bac562","analyzedAt":"2026-08-16T03:46:07.889Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}