CherryHQ/cherry-studio · error · Error
Image generation job: provider '${providerId}' not found
Error message
Image generation job: provider '${providerId}' not found What it means
Thrown at the start of imageGenerationJobHandler.execute() when providerService.getByProviderId(providerId) returns null — the provider record is not in the database. The providerId was parsed from the job payload's uniqueModelId, so this means the provider was removed (or never existed) between enqueue and execution.
Source
Thrown at src/main/ai/provider/custom/tasks/imageGenerationJobHandler.ts:63
* `painting.id` — the row exists before enqueue) and have this handler write the
* result there, which registers `painting_file_ref` rows and makes GC correct for
* 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,View on GitHub (pinned to 726446b54c)
Solutions
- Confirm the provider still exists: check providerService.getByProviderId(providerId) before enqueue and at execution.
- If the provider was intentionally removed, fail the job with a user-facing 'provider removed' message and clean up.
- Guard the uniqueModelId format (parseUniqueModelId) so malformed ids fail at enqueue, not at execute.
- Investigate DB consistency if the provider should exist.
Example fix
// before
const provider = providerService.getByProviderId(providerId)
if (!provider) throw new Error(`Image generation job: provider '${providerId}' not found`)
// after — include parse context
const provider = providerService.getByProviderId(providerId)
if (!provider) throw new Error(`Image generation job: provider '${providerId}' (from '${input.uniqueModelId}') not in DB; was it removed?`) Defensive patterns
Strategy: validation
Validate before calling
// Validate provider existence before enqueue
const provider = providerService.getByProviderId(providerId)
if (!provider) throw new Error(`Cannot enqueue: provider '${providerId}' not found`) Type guard
export function isJobProviderNotFound(e: unknown): boolean {
return e instanceof Error && /Image generation job: provider .* not found/.test(e.message)
} Try / catch
try {
await job.execute(ctx)
} catch (e) {
if (isJobProviderNotFound(e)) {
// mark job failed with user-facing 'provider removed' reason
}
throw e
} Prevention
- Validate provider existence at enqueue, not just at execute.
- Cancel in-flight jobs when a provider is deleted.
- Guard uniqueModelId format so malformed ids fail early.
When it happens
Trigger: A job is enqueued for a custom image-generation provider, then before/at execution the provider record is deleted from the DB, or the uniqueModelId's providerId segment is malformed/unknown. Because recovery is 'abandon', this surfaces during a fresh execution attempt rather than a resumed one.
Common situations: User deletes the provider while a job is queued, provider DB sync issue, uniqueModelId corruption, or a provider id typo in test fixtures.
Related errors
- Image generation job: model '${modelId}' not found for provi
- Image generation job: no async transport for '${sdkConfig.pr
- OpenAI-compatible reranking model only supports text documen
- Rerank response must contain a results array
- Rerank response results must be objects
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/38d047c1aba4b6e4.
Report an issue: GitHub.