musistudio/claude-code-router · error · Error

duration must be one of ${constraints.durations.join(", ")}

Error message

duration must be one of ${constraints.durations.join(", ")} seconds for ${target.protocol}.

What it means

Thrown when the protocol defines a fixed allowlist of durations (constraints.durations) and the supplied duration isn't in it. Some providers only accept discrete values (e.g. 5 or 10 seconds), unlike providers with a min/max range.

Source

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

  async imageEdit(args: Record<string, unknown>, modelInput: MediaModelInput): Promise<PublicMediaJob> {
    const request: ImageEditRequest = {
      aspectRatio: optionalString(args.aspect_ratio),
      images: this.validateImages(args.images ?? args.image, 1, 3),
      prompt: requiredPrompt(args.prompt)
    };
    const modelPlan = this.mediaModelPlan("image-edit", modelInput);
    return this.submitAndWait("image-edit", request, modelPlan, optionalString(args.idempotency_key));
  }

  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 = {

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Use one of the durations listed verbatim in the error message
  2. Read constraints.durations via videoGenerationConstraints(protocol) to build a dynamic picker in your UI
  3. Clamp user input to the nearest allowed value before calling

Example fix

// before
media.videoStart({ prompt, duration: 7 }, modelInput);

// after
media.videoStart({ prompt, duration: 5 }, modelInput); // protocol allows 5 or 10
Defensive patterns

Strategy: validation

Validate before calling

const c = videoGenerationConstraints(protocol);
if (c.durations && !c.durations.includes(duration)) {
  duration = c.durations.reduce((a, b) => Math.abs(b - duration) < Math.abs(a - duration) ? b : a);
}

Type guard

const isAllowedDuration = (d: number, c: VideoConstraints): boolean =>
  !c.durations || c.durations.includes(d);

Prevention

When it happens

Trigger: Passing a duration outside the protocol's discrete set — e.g. duration: 7 for a protocol that only allows [5, 10].

Common situations: Assuming any integer in a range is accepted after switching protocols; hardcoded duration values from old provider integrations; ignoring the error message that lists the allowed values.

Related errors


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