{"record":{"id":"e641aed2c4a67e23","repo":"Comfy-Org/ComfyUI","slug":"invalid-affine-shape-ext-shape","errorCode":null,"errorMessage":"Invalid affine shape: {ext.shape}","messagePattern":"Invalid affine shape: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy/ldm/depth_anything_3/transform.py","lineNumber":24,"sourceCode":"\nimport torch\nimport torch.nn.functional as F\n\n\n# -----------------------------------------------------------------------------\n# Affine 4x4 helpers\n# -----------------------------------------------------------------------------\n\n\ndef as_homogeneous(ext: torch.Tensor) -> torch.Tensor:\n    \"\"\"Promote (...,3,4) extrinsics to (...,4,4) homogeneous form. No-op when the input is already ``(...,4,4)``.\"\"\"\n    if ext.shape[-2:] == (4, 4):\n        return ext\n    if ext.shape[-2:] == (3, 4):\n        ones = torch.zeros_like(ext[..., :1, :4])\n        ones[..., 0, 3] = 1.0\n        return torch.cat([ext, ones], dim=-2)\n    raise ValueError(f\"Invalid affine shape: {ext.shape}\")\n\n\ndef affine_inverse(A: torch.Tensor) -> torch.Tensor:\n    \"\"\"Inverse of an affine matrix ``[R|T; 0 0 0 1]``.\"\"\"\n    R = A[..., :3, :3]\n    T = A[..., :3, 3:]\n    P = A[..., 3:, :]\n    return torch.cat([torch.cat([R.mT, -R.mT @ T], dim=-1), P], dim=-2)\n\n\n# -----------------------------------------------------------------------------\n# Quaternion <-> rotation matrix (xyzw / scalar-last)\n# -----------------------------------------------------------------------------\n\n\ndef _sqrt_positive_part(x: torch.Tensor) -> torch.Tensor:\n    \"\"\"sqrt(max(0, x)) with a zero subgradient where x == 0.\"\"\"\n    ret = torch.zeros_like(x)","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy/ldm/depth_anything_3/transform.py#L6-L42","documentation":"as_homogeneous() promotes camera extrinsics to 4x4 homogeneous form. It accepts only trailing shapes (...,3,4) (promotion applied) or (...,4,4) (no-op); any other trailing two dims raise ValueError with the offending shape. This is a strict contract check on pose tensors coming from dataset/loader code.","triggerScenarios":"Passing extrinsics with shapes like (...,3,3) (rotation only), (...,4) (quaternion or translation vector), (...,2,4), or non-matrix tensors. Common when a dataloader returns poses in a different convention (e.g. 4x4 already transposed to column-major, or axis-angle vectors) that was not converted first.","commonSituations":"Feeding DA3 ray/pose utilities with raw dataset camera poses (COLMAP/world-to-camera variants, quaternion+translation format); shapes corrupted by a wrong reshape or flatten earlier in the pipeline.","solutions":["Convert your pose representation to (...,3,4) or (...,4,4) [R|t] form before calling (e.g. cat rotation matrix with translation column).","If you have quaternions, use quat_to_mat (same module) first, then build the 3x4.","Print ext.shape right before the call and fix whatever upstream reshape produced the wrong dims."],"exampleFix":"# before (R only, shape (...,3,3))\nE = as_homogeneous(R)\n\n# after\nE = as_homogeneous(torch.cat([R, t.unsqueeze(-1)], dim=-1))  # (...,3,4)","handlingStrategy":"type-guard","validationCode":"assert ext.shape[-2:] in ((3, 4), (4, 4)), f\"extrinsics must end (...,3,4) or (...,4,4), got {tuple(ext.shape)}\"","typeGuard":"def is_affine_pose_tensor(ext: \"torch.Tensor\") -> bool:\n    return ext.ndim >= 2 and ext.shape[-2:] in ((3, 4), (4, 4))","tryCatchPattern":null,"preventionTips":["Standardize all pose tensors to (...,3,4) [R|t] at the dataloader boundary.","Convert quaternion/axis-angle representations before feeding pose utilities.","Log shapes once at ingestion so mis-formatted poses fail loudly at the source."],"tags":["depth-anything-3","camera-pose","shape-validation"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}