CherryHQ/cherry-studio · error · ImageModelResolutionError

Failed to resolve image model: ${modelId} for provider: ${pr

Error message

Failed to resolve image model: ${modelId} for provider: ${providerId}

What it means

resolveImageModel looks up the image model in the provider registry (registry.imageModel(`${providerId}:${modelId}`)) when a string id is given. If the registry has no such model it throws, and resolveImageModel wraps that in ImageModelResolutionError with the modelId and providerId. This fires before any network call.

Source

Thrown at packages/aiCore/src/core/runtime/executor.ts:332

            'All providers should be wrapped with wrapProvider to return V3 models.'
        )
      }
      return modelOrId
    }
  }

  /**
   * 解析图像模型:如果是字符串则创建图像模型,如果是模型则直接返回
   */
  private async resolveImageModel(modelOrId: ImageModelV3 | string): Promise<ImageModelV3> {
    try {
      if (typeof modelOrId === 'string') {
        return this.registry.imageModel(`${this.config.providerId}:${modelOrId}` as `${string}:${string}`)
      } else {
        return modelOrId
      }
    } catch (error) {
      throw new ImageModelResolutionError(
        typeof modelOrId === 'string' ? modelOrId : modelOrId.modelId,
        this.config.providerId,
        error instanceof Error ? error : undefined
      )
    }
  }

  // === 静态工厂方法 ===

  /**
   * 创建执行器 - 支持已知provider的类型安全
   */
  static create<
    TSettingsMap extends Record<string, any> = CoreProviderSettingsMap,
    T extends StringKeys<TSettingsMap> = StringKeys<TSettingsMap>
  >(
    providerId: T,
    provider: ProviderV3,

View on GitHub (pinned to 726446b54c)

Solutions

  1. Confirm the model id is a valid image model for the provider (check provider.imageModel exists for that id).
  2. Pass an already-resolved ImageModelV3 object instead of a string id to bypass registry lookup.
  3. Verify the provider supports image generation (extension supportsImageGeneration).

Example fix

// before
await executor.generateImage({ model: 'gpt-4o', prompt: '...' }) // not an image model
// after
await executor.generateImage({ model: 'dall-e-3', prompt: '...' })
// or pass a resolved model object
const imgModel = provider.imageModel('dall-e-3')
await executor.generateImage({ model: imgModel, prompt: '...' })
Defensive patterns

Strategy: validation

Validate before calling

if (typeof modelOrId === 'string') {
  try { provider.imageModel(modelOrId) } catch { throw new Error(`"${modelOrId}" is not an image model for ${providerId}`) }
}
await executor.generateImage({ model: modelOrId, prompt })

Try / catch

try {
  await executor.generateImage({ model: modelId, prompt })
} catch (e) {
  if (e instanceof ImageModelResolutionError) {
    // modelId not an image model — switch to a valid image model id or pass a resolved model object
  }
}

Prevention

When it happens

Trigger: Calling generateImage with a string model id that the provider does not expose as an image model — e.g. 'some-text-model' on a provider whose imageModel() throws for that id, or a model id that simply doesn't exist.

Common situations: Typo in the image model id; using a chat/embedding model id for image generation; provider doesn't ship imageModel; providerId/modelId mismatch after config change.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/95dbfb9272f8e8a3. Report an issue: GitHub.