musistudio/claude-code-router · error · Error

A media model must be selected.

Error message

A media model must be selected.

What it means

requiredModelSelector rejects an empty/whitespace model selector. Every media API path needs a concrete model choice; if none is configured or passed, this throws.

Source

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

  ].map(canonicalInputRoot);
  return [...new Set(roots)];
}

function canonicalInputRoot(value: string): string {
  const resolved = path.resolve(expandHome(value));
  return existsSync(resolved) ? realpathSync(resolved) : resolved;
}

function isSafeImplicitWorkingDirectory(workingDirectory: string, homeDirectory: string): boolean {
  const resolvedWorkingDirectory = path.resolve(workingDirectory);
  const resolvedHomeDirectory = path.resolve(homeDirectory);
  return resolvedWorkingDirectory !== path.parse(resolvedWorkingDirectory).root &&
    !isPathInside(resolvedHomeDirectory, resolvedWorkingDirectory);
}

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 {

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Pass an explicit non-empty model selector in the tool call
  2. Configure a default media model in app configuration
  3. Check for empty-string model values coming from env/config overrides

Example fix

// before
{ prompt: "...", model: "" }
// after
{ prompt: "...", model: "openai/gpt-image-1" }
Defensive patterns

Strategy: validation

Validate before calling

if (!model?.trim()) model = configuredDefaultMediaModel;
if (!model?.trim()) throw new Error("no model selected");

Type guard

const hasModelSelector = (m: unknown): m is string => typeof m === "string" && m.trim().length > 0;

Try / catch

try { await call(); } catch (e) { if (e instanceof Error && e.message === "A media model must be selected.") return configError(); throw e; }

Prevention

When it happens

Trigger: Passing model: "" or omitting the model argument when no default media model is configured in the app config.

Common situations: Fresh install without a default media model, config migration wiped the setting, or the caller relies on a fallback that no longer exists.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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