musistudio/claude-code-router · error · Error

Media model is not configured by a provider

Error message

Media model is not configured by a provider: ${normalizedSelector}

What it means

resolveProviderMediaTarget maps a normalized model selector to a configured provider; if no provider in the registry matches the selector (after Grok agent special-casing), the model is considered unconfigured and the call is rejected.

Solutions

  1. Verify the provider exists and is enabled in the model registry config
  2. Fix the selector to match provider/model spelling exactly
  3. Re-import or re-add the provider configuration

Example fix

// before
model: "openai/gpt-image-x"
// after
model: "openai/gpt-image-1"
Defensive patterns

Strategy: validation

Validate before calling

const registry = modelRegistryForConfig(config);
const parsed = parseProviderModelSelector(selector);
if (!parsed || !registry.findProvider(parsed.provider)) throw new Error("unknown provider");

Type guard

const isConfiguredProvider = (sel: string, config: AppConfig): boolean => { const p = parseProviderModelSelector(sel); return Boolean(p && modelRegistryForConfig(config).findProvider(p.provider)); };

Try / catch

try { resolveProviderMediaTarget(config, selector, op); } catch (e) { if (e instanceof Error && e.message.includes("not configured by a provider")) return configError(); throw e; }

Prevention

When it happens

Trigger: Naming a model whose provider prefix doesn't exist in config, or whose provider entry was removed/renamed; selector normalization/migration found no match.

Common situations: Typo'd provider prefix, sharing configs between machines with different provider lists, or provider config deleted after the selector was stored.

Related errors


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

Appendix: source

Thrown at packages/core/src/media/service.ts:728

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) {
    throw new Error(`${resolved.model} is not a ${expectedKind} generation model.`);
  }
  const provider = resolved.provider;
  const kind = expectedKind ?? modelKind;
  if (!kind || !providerSupportsMediaKind(provider, kind)) {
    throw new Error(`Provider ${provider.name} does not declare ${kind ?? "media"} generation support.`);
  }
  const protocol: GatewayMediaProtocol = kind === "video"
    ? provider.capabilities?.some((item) => item.type === "xai_video_generations") || isImportedGrokAgentProvider(provider)
      ? "xai_video_generations"
      : "openai_video_generations"
    : "openai_image_generations";
  const capability = provider.capabilities?.find((item) => item.type === protocol) ??
    (protocol === "xai_video_generations" && isImportedGrokAgentProvider(provider)
      ? provider.capabilities?.find((item) => item.type === "openai_video_generations")

View on GitHub (pinned to 99f24806c6)