musistudio/claude-code-router · error · Error

resolution must be one of ${constraints.resolutions.join(",

Error message

resolution must be one of ${constraints.resolutions.join(", ")} for ${target.protocol}.

What it means

Thrown when the supplied resolution is not in the protocol's allowed resolutions list. The message lists the accepted values so the fix is usually immediate.

Source

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

  videoStart(args: Record<string, unknown>, modelInput: MediaModelInput): PublicMediaJob {
    const modelPlan = this.mediaModelPlan("video-generate", modelInput);
    const target = resolveProviderMediaTarget(this.requireConfig(), modelPlan.modelSelector, "video-generate");
    const constraints = videoGenerationConstraints(target.protocol);
    const durationValue = numberValue(args.duration) ?? constraints.defaultDuration;
    if (durationValue === undefined) throw new Error(`duration is required for ${target.protocol}.`);
    if (!Number.isInteger(durationValue)) throw new Error("duration must be an integer number of seconds.");
    if (constraints.durations && !constraints.durations.includes(durationValue)) {
      throw new Error(`duration must be one of ${constraints.durations.join(", ")} seconds for ${target.protocol}.`);
    }
    if (constraints.durationMinimum !== undefined && constraints.durationMaximum !== undefined &&
      (durationValue < constraints.durationMinimum || durationValue > constraints.durationMaximum)) {
      throw new Error(`duration must be between ${constraints.durationMinimum} and ${constraints.durationMaximum} seconds for ${target.protocol}.`);
    }
    const resolution = optionalString(args.resolution) ?? constraints.defaultResolution;
    if (!resolution) throw new Error(`resolution is required for ${target.protocol}.`);
    if (!constraints.resolutions.includes(resolution)) {
      throw new Error(`resolution must be one of ${constraints.resolutions.join(", ")} for ${target.protocol}.`);
    }
    const aspectRatio = optionalString(args.aspect_ratio);
    if (constraints.requiredParameters.includes("aspect_ratio") && !aspectRatio) {
      throw new Error(`aspect_ratio is required for ${target.protocol}.`);
    }
    if (aspectRatio && !constraints.aspectRatios.includes(aspectRatio)) {
      throw new Error(`aspect_ratio must be one of ${constraints.aspectRatios.join(", ")} for ${target.protocol}.`);
    }
    const request: VideoGenerateRequest = {
      aspectRatio,
      duration: durationValue,
      images: args.images === undefined && args.image === undefined ? [] : this.validateImages(args.images ?? args.image, 1, 7),
      prompt: requiredPrompt(args.prompt),
      resolution
    };
    const job = this.submit("video-generate", request, modelPlan, optionalString(args.idempotency_key));
    return this.publicJob(job);
  }

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Use one of the exact values listed in the error message
  2. Populate your picker from videoGenerationConstraints(protocol).resolutions
  3. Normalize/case-fold user input against the allowlist before calling

Example fix

// before
media.videoStart({ prompt, resolution: "1920x1080" }, modelInput);

// after
media.videoStart({ prompt, resolution: "1080p" }, modelInput);
Defensive patterns

Strategy: validation

Validate before calling

const c = videoGenerationConstraints(protocol);
if (!c.resolutions.includes(resolution)) {
  throw new Error(`Allowed: ${c.resolutions.join(", ")}`);
}

Type guard

const isAllowedResolution = (r: string, c: VideoConstraints): boolean =>
  c.resolutions.includes(r);

Prevention

When it happens

Trigger: Passing e.g. resolution: "4k" for a protocol whose constraints.resolutions only includes ["480p","720p","1080p"].

Common situations: Hardcoded resolution strings from other providers ("1920x1080" vs "1080p"); user free-text resolution input; uppercase/case-mismatched values.

Related errors


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