{"record":{"id":"201c9ce7bb94c7f1","repo":"CherryHQ/cherry-studio","slug":"model-resolution-failed","errorCode":"MODEL_RESOLUTION_FAILED","errorMessage":"Failed to resolve model: ${modelId}","messagePattern":"Failed to resolve model: (.+?)","errorType":"error_code","errorClass":"ModelResolutionError","httpStatus":null,"severity":"error","filePath":"packages/aiCore/src/core/runtime/pluginEngine.ts","lineNumber":124,"sourceCode":"  /**\n   * Resolve modelId through the plugin pipeline (configureContext → resolveModel → wrapLanguageModel).\n   * Returns a middleware-wrapped LanguageModel ready for external consumers like ToolLoopAgent.\n   *\n   * Note: This is a model-resolution-only path, not a full request lifecycle.\n   * - `originalParams` in context will be `{}` since no request params exist at resolution time.\n   * - `onError` hooks are NOT invoked on failure — callers should handle errors directly.\n   */\n  async resolveModel(modelId: string): Promise<LanguageModelV3> {\n    const context = createContext(this.providerId, modelId, {})\n    const manager = new PluginManager(this.basePlugins)\n\n    // 1. configureContext — collect middlewares\n    await manager.executeConfigureContext(context)\n\n    // 2. resolveModel — string → LanguageModel\n    const resolved = await manager.executeFirst<LanguageModel>('resolveModel', modelId, context)\n    if (!resolved) {\n      throw new ModelResolutionError(modelId, this.providerId)\n    }\n    if (!isV3Model(resolved)) {\n      throw new ModelResolutionError(\n        modelId,\n        this.providerId,\n        new Error(`Provider \"${this.providerId}\" resolved a non-V3 language model`)\n      )\n    }\n\n    // 3. Apply middlewares\n    if (context.middlewares && context.middlewares.length > 0) {\n      return wrapLanguageModel({\n        model: resolved,\n        middleware: context.middlewares\n      })\n    }\n\n    return resolved","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/aiCore/src/core/runtime/pluginEngine.ts#L106-L142","documentation":"PluginEngine.resolveModel runs the plugin pipeline's 'resolveModel' hook (executeFirst) expecting a plugin to turn the string modelId into a LanguageModel. If no plugin handles it, executeFirst returns undefined and ModelResolutionError (code MODEL_RESOLUTION_FAILED) is thrown with modelId and providerId in context. The internal _internal_resolveModel plugin normally does this via the executor's registry.","triggerScenarios":"Calling resolveModel (directly or via resolveLanguageModel/streamText with a string model) when no resolveModel plugin is attached — e.g. calling executor.pluginEngine.resolveModel without first usePlugins([executor.createResolveModelPlugin()]).","commonSituations":"Using the pluginEngine standalone without registering the internal resolve plugin; calling resolveLanguageModel for a provider whose registry has no such model id; plugins were cleared/filtered removing the resolver.","solutions":["Ensure the executor's resolveModel plugin is attached (usePlugins([executor.createResolveModelPlugin()])) before resolveModel.","Prefer the high-level executor.streamText/generateText which wire the plugin automatically when model is a string.","Confirm the model id exists for the provider in the registry."],"exampleFix":"// before — engine has no resolver plugin\nconst model = await executor.pluginEngine.resolveModel('gpt-4o')\n// after\nexecutor.pluginEngine.usePlugins([executor.createResolveModelPlugin()])\nconst model = await executor.pluginEngine.resolveModel('gpt-4o')","handlingStrategy":"validation","validationCode":"if (!executor.pluginEngine.getPlugins().some((p) => p.name === '_internal_resolveModel')) {\n  executor.pluginEngine.usePlugins([executor.createResolveModelPlugin()])\n}\nawait executor.pluginEngine.resolveModel(modelId)","typeGuard":null,"tryCatchPattern":"try {\n  await executor.pluginEngine.resolveModel(modelId)\n} catch (e) {\n  if (e instanceof ModelResolutionError) {\n    // no resolver plugin attached or model id unknown — attach the plugin / verify the id\n  }\n}","preventionTips":["Prefer executor.streamText/generateText which auto-attach the resolver plugin for string models.","When using pluginEngine.resolveModel directly, always usePlugins([executor.createResolveModelPlugin()]) first.","Confirm the model id exists in the provider's registry."],"tags":["model-resolution","plugins","runtime","config"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}