{"record":{"id":"7ce7f08ff03e9025","repo":"Comfy-Org/ComfyUI","slug":"keyframe-idxs-holds-keyframe-idxs-shape-2-token","errorCode":null,"errorMessage":"keyframe_idxs holds {keyframe_idxs.shape[2]} tokens, which is not a whole number of {tokens_per_frame}-token latent frames. The appended frames were recorded against a different spatial resolution than the latent being sampled, so their positions would land on the wrong tokens. Crop the guides and separate the generated keyframes before upscaling the latent.","messagePattern":"keyframe_idxs holds (.+?) tokens, which is not a whole number of (.+?)-token latent frames\\. The appended frames were recorded against a different spatial resolution than the latent being sampled, so their positions would land on the wrong tokens\\. Crop the guides and separate the generated keyframes before upscaling the latent\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy/ldm/lightricks/model.py","lineNumber":1122,"sourceCode":"        )\n        self.proj_out = self.operations.Linear(self.inner_dim, self.out_channels, dtype=dtype, device=device)\n        self.patchifier = SymmetricPatchifier(1, start_end=True)\n\n    def _process_input(self, x, keyframe_idxs, denoise_mask, **kwargs):\n        \"\"\"Process input for LTXV.\"\"\"\n        additional_args = {\"orig_shape\": list(x.shape)}\n        x, latent_coords = self.patchifier.patchify(x)\n        pixel_coords = latent_to_pixel_coords(\n            latent_coords=latent_coords,\n            scale_factors=self.vae_scale_factors,\n            causal_fix=self.causal_temporal_positioning,\n        )\n\n        grid_mask = None\n        if keyframe_idxs is not None and keyframe_idxs.shape[2] > 0:\n            tokens_per_frame = self.tokens_per_latent_frame(additional_args[\"orig_shape\"])\n            if keyframe_idxs.shape[2] % tokens_per_frame != 0:\n                raise ValueError(\n                    f\"keyframe_idxs holds {keyframe_idxs.shape[2]} tokens, which is not a whole number of \"\n                    f\"{tokens_per_frame}-token latent frames. The appended frames were recorded against a \"\n                    \"different spatial resolution than the latent being sampled, so their positions would land \"\n                    \"on the wrong tokens. Crop the guides and separate the generated keyframes before \"\n                    \"upscaling the latent.\"\n                )\n            additional_args.update({ \"orig_patchified_shape\": list(x.shape)})\n            denoise_mask = self.patchifier.patchify(denoise_mask)[0]\n            grid_mask = ~torch.any(denoise_mask < 0, dim=-1)[0]\n            additional_args.update({\"grid_mask\": grid_mask})\n            x = x[:, grid_mask, :]\n            pixel_coords = pixel_coords[:, :, grid_mask, ...]\n\n            kf_grid_mask = grid_mask[-keyframe_idxs.shape[2]:]\n\n            # Compute per-guide surviving token counts from guide_attention_entries.\n            # Each entry tracks one guide reference; they are appended in order and\n            # their pre_filter_counts partition the kf_grid_mask.","sourceCodeStart":1104,"sourceCodeEnd":1140,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy/ldm/lightricks/model.py#L1104-L1140","documentation":"During keyframe-conditioned LTX sampling, the recorded keyframe token indices must decompose into whole latent frames at the CURRENT latent resolution (tokens_per_latent_frame of the tensor being sampled). A non-multiple means the keyframes were logged against a different spatial resolution (e.g. pre-upscale), so their token positions would be misaligned.","triggerScenarios":"Feeding keyframe_idxs recorded on the base latent into an upscaled sampling pass (2x spatial -> 4x tokens per frame), or mixing guides from one resolution with a latent of another.","commonSituations":"Two-pass workflows: generate keyframes at low res, then upscale the latent while keeping the guide/keyframe conditioning attached instead of separating it first.","solutions":["Crop the guide latent and detach the generated keyframes before upscaling, as the message says","Re-record keyframe_idxs against the new resolution if you intentionally re-scale guides","Keep all keyframe bookkeeping and the sampled latent at the same spatial resolution"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"tpf = model.tokens_per_latent_frame(list(latent.shape))\nassert keyframe_idxs.shape[2] % tpf == 0, (keyframe_idxs.shape[2], tpf)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Separate generated keyframes from guides before any latent upscale","Keep keyframe_idxs and the sampled latent at one resolution for the whole chain"],"tags":["ltx","keyframes","resolution-mismatch","upsample"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}