{"record":{"id":"7657af87f003e583","repo":"linshenkx/prompt-optimizer","slug":"model-provider-not-found","errorCode":null,"errorMessage":"Model ${provider} not found","messagePattern":"Model (.+?) not found","errorType":"validation","errorClass":"RequestConfigError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/llm/service.ts","lineNumber":90,"sourceCode":"    // Default behavior: disabled models cannot be used for normal requests.\n    // Connection testing is allowed to bypass this check (align with image model test behavior).\n    if (!options.allowDisabled && !modelConfig.enabled) {\n      throw new RequestConfigError('Model is not enabled');\n    }\n  }\n\n  /**\n   * 发送消息（结构化格式）\n   */\n  async sendMessageStructured(messages: Message[], provider: string): Promise<LLMResponse> {\n    try {\n      if (!provider) {\n        throw new RequestConfigError('Model provider cannot be empty');\n      }\n\n      const modelConfig = await this.modelManager.getModel(provider);\n      if (!modelConfig) {\n        throw new RequestConfigError(`Model ${provider} not found`);\n      }\n\n      this.validateModelConfig(modelConfig);\n      this.validateMessages(messages);\n\n      // 通过 Registry 获取 Adapter\n      const adapter = this.registry.getAdapter(modelConfig.providerMeta.id);\n\n      const runtimeConfig = this.prepareRuntimeConfig(modelConfig);\n\n      // 使用 Adapter 发送消息\n      return await adapter.sendMessage(messages, runtimeConfig);\n\n    } catch (error: any) {\n      if (error instanceof RequestConfigError || error instanceof APIError) {\n        throw error;\n      }\n      throw new APIError(`Failed to send message: ${error.message}`);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/llm/service.ts#L72-L108","documentation":"Thrown by sendMessageStructured when modelManager.getModel(provider) resolves to nothing. The provider string is accepted as non-empty but no model configuration with that id exists, so the service cannot build a request. Distinguish from 'Model provider cannot be empty': here the id was provided but unknown.","triggerScenarios":"Calling sendMessageStructured(messages, 'some-provider-id') where no model config with that id has been registered/added to the model manager. Also possible if configs are stored asynchronously and not yet loaded when the call is made.","commonSituations":"Typos or case mismatch in the provider id ('OpenAI' vs 'openai'); referencing a model the user deleted; a config store that hasn't finished initializing (race at app startup); profile or workspace switch that cleared model configs.","solutions":["List registered models (e.g. modelManager.listModels()) and verify the exact id exists, including casing","If configs load async, await model manager initialization before sending messages","Register/add the model config for that provider id, or switch the call to an id that exists"],"exampleFix":"// before\nawait llm.sendMessageStructured(msgs, 'gpt4'); // not registered\n\n// after\nconst models = await modelManager.listModels();\nconst target = models.find(m => m.providerMeta.id === 'openai');\nawait llm.sendMessageStructured(msgs, target!.providerMeta.id);","handlingStrategy":"validation","validationCode":"const cfg = await modelManager.getModel(provider);\nif (!cfg) throw new Error(`Provider \"${provider}\" is not registered. Available: ${(await modelManager.listModels()).map(m => m.providerMeta.id).join(', ')}`);","typeGuard":"async function providerExists(pm: ModelManager, id: string): Promise<boolean> { return !!(await pm.getModel(id)); }","tryCatchPattern":"catch (e) { if (e instanceof RequestConfigError && /not found/.test(e.message)) { offerModelSelection(); } }","preventionTips":["Verify ids against listModels() before requests","Await model manager initialization at app startup","Normalize provider ids (trim, lowercase) at the boundary"],"tags":["llm","not-found","model-config"],"backgroundTag":"resource-not-found","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}