musistudio/claude-code-router · error · Error
Media model is not configured by a provider: ${normalizedSel
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.
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)
Solutions
- Verify the provider exists and is enabled in the model registry config
- Fix the selector to match provider/model spelling exactly
- 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
- Lint model selectors against the registry at startup
- Pin provider names in config
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
- Provider ${provider.name} does not configure a media API bas
- No Bot Gateway conversationRef is available for media respon
- Remote media result has no URL.
- Video fallback model ${selector} uses ${target.protocol}, bu
- A media model must be selected.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/2b3dd3bb66d01014.
Report an issue: GitHub.