{"record":{"id":"e0634abcd780ad9d","repo":"linshenkx/prompt-optimizer","slug":"no-provider-or-model-selected","errorCode":null,"errorMessage":"No provider or model selected","messagePattern":"No provider or model selected","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/ui/src/composables/model/useTextModelManager.ts","lineNumber":899,"sourceCode":"      id: modelKey,\n      name: form.value.name,\n      enabled: form.value.enabled,\n      providerId: providerMeta.id,\n      modelId: modelMeta.id,\n      providerMeta,\n      modelMeta,\n      connectionConfig,\n      paramOverrides: { ...(form.value.paramOverrides ?? {}) }\n    } as TextModelConfig\n\n    await modelManager.addModel(modelKey, newConfig)\n    return modelKey\n  }\n\n  const saveForm = async () => {\n    if (isSaving.value) return null\n    if (!canSaveForm.value) {\n      throw new Error('No provider or model selected')\n    }\n    isSaving.value = true\n    try {\n      const customHeaderError = getCustomHeaderValidationMessage()\n      if (customHeaderError) {\n        throw new Error(customHeaderError)\n      }\n\n      const savedId = editingModelId.value ? await updateExistingModel() : await createNewModel()\n      await loadModels()\n      return savedId\n    } finally {\n      isSaving.value = false\n    }\n  }\n\n  const testFormConnection = async () => {\n    // 使用 canTestFormConnection 的完整校验逻辑","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/composables/model/useTextModelManager.ts#L881-L917","documentation":"saveForm throws 'No provider or model selected' when canSaveForm is false, i.e. the form lacks a providerId or a usable model id. It is a pre-flight validation error preventing an invalid model config from being persisted.","triggerScenarios":"Clicking save before selecting a provider, or before choosing/typing a model id; custom-model mode where the modelId input is still empty; canSaveForm computed incorrectly evaluating false due to a missing dependent field.","commonSituations":"Save button enabled while async provider list is still loading; user types a custom model name but the debounced modelId update hasn't committed; validation computed requires apiKey that is empty for keyless providers.","solutions":["Ensure providerId and modelId are set before calling saveForm (disable the save button unless canSaveForm is true)","If using a custom model, fill in the modelId field; check that canSaveForm's conditions match your provider type (some providers need no key)","Await provider loading so providerId can be assigned programmatically","Add inline form validation messages so the reason canSaveForm is false is visible"],"exampleFix":"// before\nif (!canSaveForm.value) {\n  throw new Error('No provider or model selected')\n}\n\n// after\nif (!canSaveForm.value) {\n  throw new Error(\n    !form.value.providerId ? 'No provider selected' : 'No model selected'\n  )\n}","handlingStrategy":"validation","validationCode":"if (!form.value.providerId || !form.value.modelId) {\n  // disable save / show field errors; do not call saveForm\n}","typeGuard":"const isFormSubmittable = (f: { providerId?: string; modelId?: string }): boolean =>\n  Boolean(f.providerId && f.modelId)","tryCatchPattern":"try { await saveForm() } catch (e) { if (String(e?.message) === 'No provider or model selected') { focusFirstMissingField() } else throw e }","preventionTips":["Bind the save button's disabled state to canSaveForm","Show per-field validation so the missing field is obvious","Await provider load before allowing programmatic save"],"tags":["form-validation","model-manager","required-fields"],"backgroundTag":"required-field-missing","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}