{"record":{"id":"f8b3fecfd8e76d12","repo":"Comfy-Org/ComfyUI","slug":"triposplat-gaussian-decoder-use-the-triposplat-d","errorCode":null,"errorMessage":"TripoSplat gaussian decoder: use the 'TripoSplat Decode' (VAEDecodeTripoSplat)","messagePattern":"TripoSplat gaussian decoder: use the 'TripoSplat Decode' \\(VAEDecodeTripoSplat\\)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"comfy/sd.py","lineNumber":1041,"sourceCode":"                self.working_dtypes = [torch.float32]\n                # encode gets the waveform shape [B, 2, samples], decode the latent shape [B, 32, 2, T]\n                def estimate_encode_memory(samples, dtype):\n                    return (900 * samples + 105_000_000) * model_management.dtype_size(dtype) * 1.03\n\n                def estimate_decode_memory(samples, dtype):\n                    return max(42_000_000, 220 * samples + 20_000_000) * model_management.dtype_size(dtype) * 1.03\n\n                self.memory_used_encode = lambda shape, dtype: estimate_encode_memory(shape[2], dtype)\n                self.memory_used_decode = lambda shape, dtype: estimate_decode_memory(shape[-1] * self.upscale_ratio, dtype)\n            elif \"gs.base_offset_scale\" in sd and \"octree.out_proj.weight\" in sd:  # TripoSplat octree gaussian decoder\n                self.first_stage_model = comfy.ldm.triposplat.vae.OctreeGaussianDecoder()\n                self.latent_channels = 16\n                self.latent_dim = 1\n                self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32]\n                # The generic VAE.encode/decode path isn't used: VAEDecodeTripoSplat calls the gaussian\n                # decoder directly (structured GaussianSplat objects, not a tensor and reserves VRAM itself from num_gaussians.\n                def _no_generic_io(*args, **kwargs):\n                    raise RuntimeError(\"TripoSplat gaussian decoder: use the 'TripoSplat Decode' (VAEDecodeTripoSplat)\")\n                self.memory_used_encode = self.memory_used_decode = _no_generic_io\n            else:\n                logging.warning(\"WARNING: No VAE weights detected, VAE not initalized.\")\n                self.first_stage_model = None\n                return\n        else:\n            self.first_stage_model = AutoencoderKL(**(config['params']))\n        self.first_stage_model = self.first_stage_model.eval()\n\n        if device is None:\n            device = model_management.vae_device()\n        self.device = device\n        offload_device = model_management.vae_offload_device()\n        if dtype is None:\n            dtype = model_management.vae_dtype(self.device, self.working_dtypes)\n        self.vae_dtype = dtype\n        self.first_stage_model.to(self.vae_dtype)\n        model_management.archive_model_dtypes(self.first_stage_model)","sourceCodeStart":1023,"sourceCodeEnd":1059,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy/sd.py#L1023-L1059","documentation":"The TripoSplat octree Gaussian decoder ('gs.base_offset_scale' + 'octree.out_proj.weight' checkpoints) does not return tensors from encode/decode: it produces structured GaussianSplat objects and manages its own VRAM. The generic VAE.encode/decode entry points are therefore replaced with a stub raising this RuntimeError, pointing users to the dedicated VAEDecodeTripoSplat node.","triggerScenarios":"Loading a TripoSplat VAE and connecting it to VAEDecode, VAEEncode, VAEDecodeTiled, or any custom node that calls vae.decode(latents) expecting an image tensor; generic workflow templates applied to a TripoSplat model.","commonSituations":"Reusing image-VAE workflows for the TripoSplat 3D model; custom nodes that call first_stage_model decode generically; API consumers assuming every VAE yields tensors.","solutions":["Use the 'TripoSplat Decode' (VAEDecodeTripoSplat) node to decode TripoSplat latents into Gaussian splats.","Branch on the VAE checkpoint keys (presence of 'gs.base_offset_scale' and 'octree.out_proj.weight') or the decoder class before choosing the decode path.","Do not connect this VAE to encode nodes; TripoSplat generation starts from model latents."],"exampleFix":"# before\nimages = vae.decode(latent)  # RuntimeError for TripoSplat octree VAE\n\n# after\n# in the workflow use node: VAEDecodeTripoSplat(vae, samples) -> GAUSSIAN_SPLATS\nsplats = nodes.VAEDecodeTripoSplat().decode(vae, latent)[0]","handlingStrategy":"validation","validationCode":"sd_keys = vae_sd.keys()\nis_tripo_splat = 'gs.base_offset_scale' in sd_keys and 'octree.out_proj.weight' in sd_keys\nassert not is_tripo_splat or use_tripo_node, 'Use VAEDecodeTripoSplat for the TripoSplat octree VAE'","typeGuard":"def is_tripo_splat_vae(vae) -> bool:\n    return isinstance(getattr(vae, 'first_stage_model', None),\n                      comfy.ldm.triposplat.vae.OctreeGaussianDecoder)","tryCatchPattern":"try:\n    out = vae.decode(latent)\nexcept RuntimeError as e:\n    if 'TripoSplat' in str(e):\n        raise SystemExit('Decode TripoSplat latents with the VAEDecodeTripoSplat node.')\n    raise","preventionTips":["Do not apply generic image-VAE workflow templates to TripoSplat models.","Branch decode paths on the Gaussian-decoder class or checkpoint signature keys."],"tags":["vae","triposplat","gaussian-splatting","unsupported-operation"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}