{"record":{"id":"c6a56c80cf60e292","repo":"linshenkx/prompt-optimizer","slug":"provider-not-found-selectedproviderid-value","errorCode":null,"errorMessage":"Provider not found: ${selectedProviderId.value}","messagePattern":"Provider not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/composables/model/useImageModelManager.ts","lineNumber":610,"sourceCode":"      const isEditing = !!configForm.value.id\n      applyDefaultsFromModel(isEditing)\n    }\n  }\n\n  // 保存配置（优化版本：使用缓存的模型对象）\n  const saveConfig = async () => {\n    if (!configForm.value.name || !selectedProviderId.value || !selectedModelId.value) {\n      toast.error(t('image.config.incomplete'))\n      return\n    }\n\n    isSaving.value = true\n\n    try {\n      const cachedProvider = providers.value.find(p => p.id === selectedProviderId.value)\n\n      if (!cachedProvider) {\n        throw new Error(`Provider not found: ${selectedProviderId.value}`)\n      }\n\n      // 获取模型信息：优先使用缓存，不存在时通过registry构建\n      let cachedModel = models.value.find(m => m.id === selectedModelId.value)\n      if (!cachedModel) {\n        // 对于自定义模型ID，使用adapter的buildDefaultModel方法构建\n        try {\n          const adapter = registry.getAdapter(selectedProviderId.value)\n          cachedModel = adapter.buildDefaultModel(selectedModelId.value)\n        } catch (error) {\n          throw new Error(\n            `Unable to build model ${selectedModelId.value}: ${error instanceof Error ? error.message : String(error)}`,\n            { cause: error }\n          )\n        }\n      }\n\n      // Manager owns authoritative provider/model metadata resolution.","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/composables/model/useImageModelManager.ts#L592-L628","documentation":"saveConfig in useImageModelManager looks up the currently selected provider by selectedProviderId in the local providers cache; if the ID isn't found it aborts with 'Provider not found'. This is a state-consistency error: the selection points at a provider that isn't (or no longer) in the loaded provider list.","triggerScenarios":"Saving an image model config after the provider list was reloaded/filtered so the selected provider ID is stale; a race between provider loading and save; or selectedProviderId set to an ID that never existed.","commonSituations":"User leaves the config dialog open while providers refresh in the background; provider uninstalled/removed while dialog open; restored persisted selectedProviderId referencing a removed provider.","solutions":["Reload/refresh the provider list and re-select the provider before saving.","Validate that selectedProviderId still exists in providers whenever the list changes (watch) and reset selection if not.","Clear stale persisted selection state on startup."],"exampleFix":"// before\nconst cachedProvider = providers.value.find(p => p.id === selectedProviderId.value)\nif (!cachedProvider) throw new Error(`Provider not found: ...`)\n\n// after — guard before opening save\nif (!providers.value.some(p => p.id === selectedProviderId.value)) {\n  await loadProviders()\n  selectedProviderId.value = providers.value[0]?.id ?? null\n}\n// then save","handlingStrategy":"validation","validationCode":"if (!providers.value.some(p => p.id === selectedProviderId.value)) { await loadProviders(); /* reselect */ }","typeGuard":"const isKnownProvider = (id: string) => providers.value.some(p => p.id === id)","tryCatchPattern":"catch (e) { if (e instanceof Error && e.message.startsWith('Provider not found')) { await loadProviders(); return } throw e }","preventionTips":["Revalidate selection whenever providers reload","Clear persisted selectedProviderId if it no longer exists"],"tags":["stale-state","provider-selection","persistence"],"backgroundTag":"stale-reference-id","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}