{"record":{"id":"8a948f46babb1dbc","repo":"invoke-ai/InvokeAI","slug":"video-at-video-path-reports-invalid-dimensions","errorCode":null,"errorMessage":"Video at {video_path} reports invalid dimensions {width}x{height}","messagePattern":"Video at (.+?) reports invalid dimensions (.+?)x(.+?)","errorType":"validation","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"invokeai/app/util/video_thumbnails.py","lineNumber":431,"sourceCode":"    they come from the uploaded container, and the upload path persists them and sizes\n    thumbnail decoding by them. A non-finite or non-positive fps is coerced to None\n    (unknown) rather than rejected, matching the decoder's own unknown-fps behavior.\n    \"\"\"\n    result = _run_worker([\"probe\", str(video_path)], timeout)\n    if result is None:\n        raise FileNotFoundError(f\"Unable to open video at {video_path}\")\n    try:\n        width = int(result[\"width\"])\n        height = int(result[\"height\"])\n        duration = float(result[\"duration\"])\n        fps_raw = result.get(\"fps\")\n        fps: Optional[float] = float(fps_raw) if fps_raw else None\n        codec_raw = result.get(\"codec\")\n        codec = str(codec_raw).lower() if codec_raw else None\n    except (KeyError, TypeError, ValueError, OverflowError) as e:\n        raise FileNotFoundError(f\"Unable to open video at {video_path}\") from e\n    if width <= 0 or height <= 0 or width * height > MAX_VIDEO_FRAME_PIXELS:\n        raise FileNotFoundError(f\"Video at {video_path} reports invalid dimensions {width}x{height}\")\n    if not math.isfinite(duration) or duration < 0:\n        raise FileNotFoundError(f\"Video at {video_path} reports an invalid duration {duration}\")\n    if fps is not None and (not math.isfinite(fps) or fps <= 0):\n        fps = None\n    return width, height, duration, fps, codec\n\n\ndef probe_video(\n    video_path: Path, timeout: float = VIDEO_DECODE_TIMEOUT_SECONDS\n) -> tuple[int, int, float, Optional[float]]:\n    \"\"\"Returns validated video metadata without the codec.\"\"\"\n    width, height, duration, fps, _codec = probe_video_with_codec(video_path, timeout)\n    return width, height, duration, fps\n\n\ndef decoder_frame_count(video_path: Path, timeout: float = VIDEO_DECODE_TIMEOUT_SECONDS) -> Optional[int]:\n    \"\"\"Returns the exact decoded frame count, or None if it cannot be determined in time.\n","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/util/video_thumbnails.py#L413-L449","documentation":"probe_video_with_codec validates probed dimensions: width/height must be positive and width*height must not exceed MAX_VIDEO_FRAME_PIXELS. If ffprobe returns non-positive or absurdly large dimensions, the video is rejected as FileNotFoundError to prevent downstream OOM or division errors.","triggerScenarios":"Calling probe_video on a video whose ffprobe stream reports width or height of 0 or negative, or a frame size whose pixel count exceeds MAX_VIDEO_FRAME_PIXELS (e.g. 64K resolution or fabricated metadata).","commonSituations":"Corrupted stream metadata (streams without a video track), exotic/oversized resolutions users uploaded, test fixtures with fake ffprobe output, or probing audio-only files where width/height default to 0.","solutions":["Inspect the file with ffprobe -show_streams and confirm the video stream's width/height.","Remove or reject files exceeding the pixel cap; ask users to downscale (e.g. 4K max).","Remux/re-encode with ffmpeg to fix broken stream headers.","If legitimate huge videos are required, raise MAX_VIDEO_FRAME_PIXELS consciously with memory budgeting."],"exampleFix":"# before\nw, h, dur, fps, codec = probe_video(path)\n# after\nw, h, dur, fps, codec = probe_video(path)\nif w * h > 8_294_400:  # 4K guard of your own\n    raise ValueError(f\"{path} exceeds supported resolution {w}x{h}\")","handlingStrategy":"validation","validationCode":"def check_dimensions(path, max_pixels=8_294_400):\n    import subprocess, json\n    out = subprocess.run([\"ffprobe\",\"-v\",\"error\",\"-select_streams\",\"v:0\",\"-print_format\",\"json\",\"-show_streams\",path], capture_output=True)\n    streams = json.loads(out.stdout or \"{}\").get(\"streams\", [])\n    if not streams:\n        raise ValueError(f\"{path}: no video stream\")\n    w, h = streams[0].get(\"width\", 0), streams[0].get(\"height\", 0)\n    if w <= 0 or h <= 0:\n        raise ValueError(f\"{path}: invalid dimensions {w}x{h}\")\n    if w * h > max_pixels:\n        raise ValueError(f\"{path}: {w}x{h} exceeds pixel cap\")","typeGuard":"def has_valid_dimensions(probe: dict) -> bool:\n    w, h = probe.get(\"width\", 0), probe.get(\"height\", 0)\n    return w > 0 and h > 0 and w * h <= 8_294_400","tryCatchPattern":"try:\n    w, h, dur, fps, codec = probe_video(path)\nexcept FileNotFoundError as e:\n    raise ValueError(\"video dimensions are invalid or oversized; transcode before use\") from e","preventionTips":["Enforce max resolution at upload time (e.g. 4K).","Reject or transcode exotic codecs before ingestion.","Validate ffprobe output shape in tests with fixtures.","Keep MAX_VIDEO_FRAME_PIXELS aligned with your memory budget."],"tags":["video","ffprobe","validation","dimensions"],"backgroundTag":"invalid-video-dimensions","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}