{"record":{"id":"fb03df00697cd93d","repo":"sgl-project/sglang","slug":"camera-trajectory-must-have-shape-f-4-4-got","errorCode":null,"errorMessage":"camera trajectory must have shape (F, 4, 4); got {c2w.shape}","messagePattern":"camera trajectory must have shape \\(F, 4, 4\\); got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/base.py","lineNumber":227,"sourceCode":"        if \"s\" in held:\n            move -= forward * translation_speed\n        if \"d\" in held:\n            move += right * translation_speed\n        if \"a\" in held:\n            move -= right * translation_speed\n\n        current = np.eye(4, dtype=np.float64)\n        current[:3, :3] = rotation\n        current[:3, 3] = translation + move\n        poses.append(current.copy())\n\n    return np.stack(poses, axis=0).astype(np.float32)\n\n\ndef sana_wm_load_camera(path: Path) -> np.ndarray:\n    c2w = np.load(path).astype(np.float32)\n    if c2w.ndim != 3 or c2w.shape[1:] != (4, 4):\n        raise ValueError(\n            f\"camera trajectory must have shape (F, 4, 4); got {c2w.shape}\"\n        )\n    return c2w\n\n\ndef sana_wm_load_intrinsics(path: Path, num_frames: int) -> np.ndarray:\n    arr = np.load(path).astype(np.float32)\n    if arr.shape == (4,):\n        return np.broadcast_to(arr, (num_frames, 4)).copy()\n    if arr.shape == (3, 3):\n        vec = np.array([arr[0, 0], arr[1, 1], arr[0, 2], arr[1, 2]], dtype=np.float32)\n        return np.broadcast_to(vec, (num_frames, 4)).copy()\n    if arr.ndim == 3 and arr.shape[1:] == (3, 3) and arr.shape[0] >= num_frames:\n        arr = arr[:num_frames]\n        return np.stack(\n            [arr[:, 0, 0], arr[:, 1, 1], arr[:, 0, 2], arr[:, 1, 2]], axis=1\n        )\n    raise ValueError(","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/base.py#L209-L245","documentation":"Raised by sana_wm_load_camera when an .npy file loaded from path does not have shape (F, 4, 4) — i.e. not a 3D array of 4x4 camera-to-world matrices, one per frame.","triggerScenarios":"Calling sana_wm_load_camera on an .npy containing a single (4,4) matrix (ndim=2), a (F,3,3) array, or arbitrary arrays. Called from _prepare_static_camera.","commonSituations":"Saved OpenCV-style w2c matrices instead of c2w; saved a single pose instead of a trajectory; exported (F,4,4) as nested lists that collapsed; wrong file passed as camera path.","solutions":["Export the trajectory as np.stack(c2w_list, axis=0) with each element 4x4","If you have a single pose, tile it: np.repeat(pose[None], F, axis=0)","Verify with arr.shape == (F,4,4) before saving"],"exampleFix":"# before\nnp.save(path, pose)  # (4,)\n# after\nnp.save(path, np.repeat(np.eye(4)[None], num_frames, axis=0))  # (F,4,4)","handlingStrategy":"validation","validationCode":"arr = np.load(path)\nassert arr.ndim == 3 and arr.shape[1:] == (4, 4), f'{path}: {arr.shape}'","typeGuard":"def is_trajectory(a) -> bool:\n    import numpy as np\n    return a.ndim == 3 and a.shape[1:] == (4, 4)","tryCatchPattern":null,"preventionTips":["Validate .npy shape right after np.load in data prep scripts","Save trajectories with np.stack(poses, axis=0)"],"tags":["numpy","camera-trajectory","shape-validation","sana-wm"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}