{"record":{"id":"5dcbaf58a6bde07c","repo":"invoke-ai/InvokeAI","slug":"the-requested-transition-needs-an-estimated-estim","errorCode":null,"errorMessage":"The requested transition needs an estimated {estimated_mib:.0f} MiB, which exceeds the {limit_mib:.0f} MiB transition memory budget. Lower transition_frames or use lower-resolution clips.","messagePattern":"The requested transition needs an estimated (.+?) MiB, which exceeds the (.+?) MiB transition memory budget\\. Lower transition_frames or use lower-resolution clips\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/video_concat.py","lineNumber":209,"sourceCode":"            return float(self.fps)\n        known_rates = [rate for rate in source_rates if rate is not None and rate > 0]\n        if not known_rates:\n            return 16.0\n        if any(not math.isclose(rate, known_rates[0], rel_tol=1e-3) for rate in known_rates[1:]):\n            raise ValueError(\"Input videos have different frame rates; set Output FPS to retime them.\")\n        # An unknown rate mixed with agreeing known ones is not an error: probe_video\n        # deliberately reports None for metadata-poor containers (VFR flags, missing\n        # avg_frame_rate) whose real rate is usually the same as their neighbours'.\n        # Erroring here would break previously-working concat workflows over a metadata\n        # quirk; disagreement between *known* rates is the case that silently retimes.\n        return known_rates[0]\n\n    def _validate_transition_memory(self, width: int, height: int) -> None:\n        estimated_bytes = self._estimate_transition_memory(width, height)\n        if estimated_bytes > MAX_TRANSITION_MEMORY_BYTES:\n            estimated_mib = estimated_bytes / (1024 * 1024)\n            limit_mib = MAX_TRANSITION_MEMORY_BYTES / (1024 * 1024)\n            raise ValueError(\n                f\"The requested transition needs an estimated {estimated_mib:.0f} MiB, \"\n                f\"which exceeds the {limit_mib:.0f} MiB transition memory budget. \"\n                \"Lower transition_frames or use lower-resolution clips.\"\n            )\n\n    def _iter_joined_frames(\n        self,\n        clips: list[Iterable[np.ndarray]],\n        is_canceled: Optional[Callable[[], bool]] = None,\n    ) -> Iterator[np.ndarray]:\n        \"\"\"Yields the joined output frames, pulling lazily from each clip's frame iterator.\n\n        A frame is emitted as soon as it can no longer participate in a transition, so at\n        most one transition window (the previous clip's tail plus the current clip's head,\n        each bounded by ``transition_frames``) is buffered at a time — never a whole clip.\n\n        Transition layout matches the class docstring:\n","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/video_concat.py#L191-L227","documentation":"Thrown by _validate_transition_memory when the estimated RAM needed to hold crossfade transition frames exceeds MAX_TRANSITION_MEMORY_BYTES. The estimate scales with clip width, height, and transition_frames, so high-resolution clips or large transition windows blow the budget. The library fails fast instead of being killed by OOM.","triggerScenarios":"Calling invoke() on a VideoConcat invocation where _estimate_transition_memory(width, height) = f(width*height*transition_frames) exceeds MAX_TRANSITION_MEMORY_BYTES.","commonSituations":"Users concat 1080p/4K clips with large transition_frames values; budget default sized for 720p; misconfigured MAX_TRANSITION_MEMORY_BYTES constant too small.","solutions":["Reduce the transition_frames field on the invocation","Use lower-resolution clips (downscale inputs before concat)","Lower width/height by pre-scaling the video files","Increase MAX_TRANSITION_MEMORY_BYTES if the machine has enough RAM"],"exampleFix":"// before\nvc = VideoConcat(videos=clips, transition_frames=60)  # 1080p clips, 4096 MiB budget exceeded\n// after\nvc = VideoConcat(videos=clips, transition_frames=15)  # fits budget","handlingStrategy":"validation","validationCode":"est_mib = (width * height * transition_frames * 4) / (1024*1024)\nif est_mib > 4096:\n    raise ValueError('transition memory budget exceeded; lower transition_frames')","typeGuard":null,"tryCatchPattern":"try:\n    out = invocation.invoke(context)\nexcept ValueError as e:\n    if 'transition memory budget' in str(e):\n        transition_frames = max(1, transition_frames // 2)\n        out = rebuild_invocation(transition_frames).invoke(context)\n    else:\n        raise","preventionTips":["Compute estimated memory before invoking","Keep transition_frames small relative to resolution","Downscale 4K inputs before concat"],"tags":["memory","video","validation"],"backgroundTag":"memory-budget-exceeded","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}