CherryHQ/cherry-studio · error · Error
Image generation job: model '${modelId}' not found for provi
Error message
Image generation job: model '${modelId}' not found for provider '${providerId}' What it means
Thrown immediately after the provider lookup in imageGenerationJobHandler.execute() when modelService.getByKey(providerId, modelId) returns null — the model record is missing for that provider. Like 397, it reflects a stale payload: the model existed at enqueue time but not at execution.
Source
Thrown at src/main/ai/provider/custom/tasks/imageGenerationJobHandler.ts:65
* free. Then switch `recovery` back to `'retry'` and restore the resume branch from
* the recipe in `docs/references/job-and-scheduler/handler-authoring.md`.
*/
export const imageGenerationJobHandler: JobHandler<ImageGenerationJobPayload> = {
recovery: 'abandon',
defaultQueue: (input) => `image-generation.${parseUniqueModelId(input.uniqueModelId).providerId}`,
defaultConcurrency: 2,
// The transport already retries transient poll errors internally; a job-level
// retry would re-submit and burn the user's vendor quota, so cap at 1 attempt
// (parity with agent.task).
defaultRetryPolicy: { maxAttempts: 1, backoff: 'none', baseDelayMs: 0, maxDelayMs: 0 },
defaultTimeoutMs: 30 * 60_000,
async execute(ctx) {
const input = ctx.input
const { providerId, modelId } = parseUniqueModelId(input.uniqueModelId)
const provider = providerService.getByProviderId(providerId)
if (!provider) throw new Error(`Image generation job: provider '${providerId}' not found`)
const model = modelService.getByKey(providerId, modelId)
if (!model) throw new Error(`Image generation job: model '${modelId}' not found for provider '${providerId}'`)
const { config, credentialReceipt } = await resolveProviderAiSdkConfig(provider, model)
const sdkConfig = {
...config,
modelId: resolveWireModelId(model, resolveEffectiveEndpoint(provider, model).endpointType)
}
// Built fresh every execution and held in memory only. Upstream persists this
// to job metadata so a resumed run can still attribute its cost; with
// `recovery: 'abandon'` no run outlives the process, so persisting it would be
// a write nobody reads — and would imply a durability this handler does not have.
const captureContext = createAiUsageCaptureContext({
providerId: provider.id,
providerName: provider.name,
modelId: sdkConfig.modelId,
modelName: model.name,
pricing: model.pricing,
trustProviderReportedCost: provider.apiFeatures.reportsActualCost,
reportedCostCurrency: provider.reportedCostCurrency,View on GitHub (pinned to 726446b54c)
Solutions
- Confirm the model still exists: check modelService.getByKey(providerId, modelId) before enqueue and at execution.
- If the model was removed, fail the job with a user-facing 'model removed' message.
- Validate the provider↔model pairing when building uniqueModelId.
- Investigate model catalog sync if the model should exist.
Example fix
// before
const model = modelService.getByKey(providerId, modelId)
if (!model) throw new Error(`Image generation job: model '${modelId}' not found for provider '${providerId}'`)
// after — hint at the likely cause
if (!model) throw new Error(`Image generation job: model '${modelId}' for provider '${providerId}' not in DB; was it removed or renamed?`) Defensive patterns
Strategy: validation
Validate before calling
const model = modelService.getByKey(providerId, modelId)
if (!model) throw new Error(`Cannot enqueue: model '${modelId}' not found for provider '${providerId}'`) Type guard
export function isJobModelNotFound(e: unknown): boolean {
return e instanceof Error && /Image generation job: model .* not found/.test(e.message)
} Try / catch
try {
await job.execute(ctx)
} catch (e) {
if (isJobModelNotFound(e)) {
// mark job failed with user-facing 'model removed' reason
}
throw e
} Prevention
- Validate model existence at enqueue.
- Cancel in-flight jobs when a model is deleted or renamed.
- Verify provider↔model pairing when constructing uniqueModelId.
When it happens
Trigger: A job enqueued for a specific provider+model combination, but the model record was deleted (or provider/model mismatch) before execution. The modelId is parsed from uniqueModelId; a wrong pairing or a removed model triggers it.
Common situations: User removes the model while a job is queued, model sync lag, modelId drift after a rename, or uniqueModelId built with the wrong provider/model pairing.
Related errors
- Image generation job: provider '${providerId}' not found
- imageModel
- Unknown model: ${input.modelId}
- Image generation job: no async transport for '${sdkConfig.pr
- OpenAI-compatible reranking model only supports text documen
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/2e1b8b59156cff4f.
Report an issue: GitHub.