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

  1. Resume only jobs created by the current version that carry a model binding
  2. Re-issue the original request as a new job instead of resuming
  3. 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

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


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/6f92b20a715d80a1. Report an issue: GitHub.