musistudio/claude-code-router · error · Error
This media job has no media API model binding and cannot be
Error message
This media job has no media API model binding and cannot be resumed.
What it means
jobModelSelector(job) reads the persisted modelSelector on a media job; resume paths require it because a resumed job must rebind to the same media API model. Jobs created without a model binding (legacy or non-API jobs) cannot be resumed.
Source
Thrown at packages/core/src/media/service.ts:713
}
function requiredModelSelector(value: string): string {
const selector = value?.trim();
if (!selector) throw new Error("A media model must be selected.");
return selector;
}
function isProviderApiJob(job: MediaJob): boolean {
const backend = (job as unknown as { backend?: string }).backend;
return backend === "gateway-media-api" || backend === "provider-api" || backend === "xai-api";
}
function jobModelSelector(job: MediaJob): string;
function jobModelSelector(job: MediaJob, required: false): string | undefined;
function jobModelSelector(job: MediaJob, required = true): string | undefined {
const selector = optionalString((job as Partial<MediaJob>).modelSelector);
if (selector) return selector;
if (required) throw new Error("This media job has no media API model binding and cannot be resumed.");
return undefined;
}
export function resolveProviderMediaTarget(config: AppConfig, selector: string, operation?: MediaOperation): GatewayMediaTarget {
const normalizedSelector = normalizeMediaModelSelector(config, selector, operation);
const registry = modelRegistryForConfig(config);
let resolved = registry.resolveProviderModel(normalizedSelector);
if (!resolved) {
const parsed = parseProviderModelSelector(normalizedSelector);
const provider = parsed ? registry.findProvider(parsed.provider) : undefined;
if (provider && isImportedGrokAgentProvider(provider) && grokMediaModelKind(parsed?.model)) {
resolved = { model: parsed!.model, provider };
}
}
if (!resolved) throw new Error(`Media model is not configured by a provider: ${normalizedSelector}`);
const expectedKind = operation === "video-generate" ? "video" : operation ? "image" : undefined;
const modelKind = grokMediaModelKind(resolved.model);
if (expectedKind && modelKind && modelKind !== expectedKind) {View on GitHub (pinned to 99f24806c6)
Solutions
- Resume only jobs created by the current version that carry a model binding
- Re-issue the original request as a new job instead of resuming
- Migrate old job records to include modelSelector if resume support is required
Example fix
// before
const job = service.resumeJob(legacyJob.id);
// after
const job = service.submitJob({ ...legacyJob.request }); // fresh job Defensive patterns
Strategy: try-catch
Validate before calling
const canResume = Boolean((job as Partial<MediaJob>).modelSelector);
Type guard
const isResumableJob = (job: unknown): job is { modelSelector: string } => typeof (job as { modelSelector?: unknown }).modelSelector === "string" && (job as { modelSelector: string }).modelSelector.length > 0; Try / catch
try { service.resume(job.id); } catch (e) { if (e instanceof Error && e.message.includes("cannot be resumed")) return resubmit(job); throw e; } Prevention
- Don't persist resume intent across versions
- Re-submit old jobs instead of resuming
When it happens
Trigger: Calling a resume/retry API on a job whose stored record lacks modelSelector — typically jobs created before model binding was tracked.
Common situations: Upgrading the service and resuming jobs persisted by an older version; jobs created through a local backend rather than a media API provider.
Related errors
- No Bot Gateway conversationRef is available for media respon
- The CCR artifact endpoint returned a non-media content type.
- The CCR media artifact exceeds the inline preview size limit
- Compressed CCR media artifacts are not accepted for inline p
- The CCR artifact response was empty.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/6f92b20a715d80a1.
Report an issue: GitHub.