unslothai/unsloth · error · ValueError
width and height must be sent together, or both omitted
Error message
width and height must be sent together, or both omitted
What it means
Raised by the _keyframe_canvas_needs_both_axes model_validator on VideoGenerateRequest. For KEYFRAME requests only (first_frame or last_frame set), the width/height canvas must be either fully specified or fully omitted, because the backend's _resolve_keyframes silently matches the source aspect ratio whenever either axis is missing — a half-specified canvas would be accepted but drawn differently than requested. The validator deliberately returns early for non-keyframe requests, since other model families (LTX, Wan, Hunyuan) and prompt-only H3 calls have always allowed a single axis to be resolved from family defaults.
Source
Thrown at studio/backend/models/inference.py:3812
"keyframes and references cannot be combined: MiniMax-H3 runs them against "
"different denoiser partitions"
)
return self
@model_validator(mode = "after")
def _keyframe_canvas_needs_both_axes(self) -> "VideoGenerateRequest":
# Omit both axes for "match source", or provide both for an explicit canvas.
# KEYFRAME requests only. There a half-specified canvas is silently discarded:
# _resolve_keyframes matches the source aspect whenever either axis is missing, so the
# axis that was sent never reaches the render and the API would accept one recipe and
# draw another. Without a keyframe the backend deliberately resolves the missing axis
# from the family's default preset -- validate_video_request_shape and generate() both
# document and implement that -- so applying the rule to every request would reject
# half-specified LTX, Wan, Hunyuan and prompt-only H3 calls that have always been valid.
if not (self.first_frame or self.last_frame):
return self
if (self.width is None) != (self.height is None):
raise ValueError("width and height must be sent together, or both omitted")
return self
class GalleryVideo(BaseModel):
"""A persisted clip's full generation recipe (the JSON sidecar of the MP4)."""
id: str = Field(..., description = "Stable id (the on-disk filename stem)")
url: str = Field(..., description = "Relative URL to fetch the MP4 bytes")
prompt: str = Field(..., description = "Prompt used")
negative_prompt: Optional[str] = Field(None, description = "Negative prompt, if any")
width: int = Field(..., description = "Frame width")
height: int = Field(..., description = "Frame height")
num_frames: int = Field(..., description = "Number of frames")
fps: int = Field(..., description = "Playback frame rate")
duration_s: float = Field(..., description = "Clip duration in seconds")
steps: int = Field(..., description = "Denoising steps")
guidance: float = Field(..., description = "Guidance scale")
guidance_2: Optional[float] = Field(View on GitHub (pinned to 203007d190)
Solutions
- Send both width and height together for keyframe requests (compute the missing axis from the keyframe image's aspect ratio).
- Or send neither axis and let the backend match the source aspect ratio of the keyframe.
- Check your request builder for conditionally-set axis fields and make them all-or-nothing when first_frame/last_frame is present.
Example fix
# before
req = {"prompt": p, "first_frame": b64, "width": 1280} # height missing
# after (explicit canvas)
req = {"prompt": p, "first_frame": b64, "width": 1280, "height": 720}
# after (match source aspect)
req = {"prompt": p, "first_frame": b64} Defensive patterns
Strategy: validation
Validate before calling
def canvas_pairwise(req: dict) -> bool:
if not (req.get("first_frame") or req.get("last_frame")):
return True
return (req.get("width") is None) == (req.get("height") is None) Type guard
function canvasOk(req: { first_frame?: unknown; last_frame?: unknown; width?: number | null; height?: number | null }): boolean {
if (!(req.first_frame || req.last_frame)) return true;
return (req.width == null) === (req.height == null);
} Prevention
- For keyframe requests compute the missing axis from the keyframe image aspect ratio before submit
- Treat width/height as one optional pair in request types (one object or null), not two independent optional fields
When it happens
Trigger: POST to video generation with first_frame or last_frame set and exactly one of width/height provided, e.g. {"first_frame": b64, "width": 1280} with height omitted, or {"last_frame": b64, "height": 720} with width omitted.
Common situations: A UI where width comes from one input and height from a possibly-unset second input; code that computes height from an aspect ratio and passes it only when the math succeeds; copying a non-keyframe request template (where one axis is fine) and adding a keyframe to it.
Related errors
- keyframes and references cannot be combined: MiniMax-H3 runs
- MiniMax-H3 takes at most 12 references in total, got {total}
- reference audio needs at least one reference image or video
- MiniMax-H3 supports aspect ratios from 1:4 to 4:1; this imag
- The aspect ratio must be positive, got {aspect_width}:{aspec
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/fb7bef1b7f5f4854.
Report an issue: GitHub.