{"record":{"id":"7781d2747b3bd3f7","repo":"Genesis-Embodied-AI/genesis-world","slug":"only-one-ellipsis-is-allowed","errorCode":null,"errorMessage":"Only one ellipsis (...) is allowed","messagePattern":"Only one ellipsis \\(\\.\\.\\.\\) is allowed","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"genesis/utils/misc.py","lineNumber":1097,"sourceCode":"    is_preallocated = tensor is not None\n    if is_preallocated or not skip_allocation:\n        expected_shape = [*map(len, indices_), *expected_shape[len(indices_) :]]\n        tensor = broadcast_tensor(tensor, dtype, expected_shape, dim_names).contiguous()\n\n    return tensor, tuple(indices_)\n\n\ndef get_indexed_shape(tensor_shape, indices):\n    \"\"\"Compute the resulting shape after advanced indexing without performing the operation.\"\"\"\n    ndim = len(tensor_shape)\n\n    # Expand ellipsis if present\n    ellipsis_count = sum(1 for idx in indices if idx is Ellipsis)\n    if ellipsis_count == 1:\n        idx = indices.index(Ellipsis)\n        indices = (*indices[:idx], *(slice(None),) * (ndim - len(indices) + 1), *indices[idx + 1 :])\n    elif ellipsis_count > 1:\n        raise IndexError(\"Only one ellipsis (...) is allowed\")\n\n    # Compute the broadcasted shape of all tensor indices\n    broadcast_shape = torch.broadcast_shapes(*[idx.shape for idx in indices if isinstance(idx, torch.Tensor)])\n\n    # Build output shape\n    output_shape = []\n    curr_idx = 0\n    inserted_broadcast = False\n    for idx in indices:\n        if isinstance(idx, int):\n            curr_idx += 1\n        elif isinstance(idx, slice):\n            start, stop, step = idx.indices(tensor_shape[curr_idx])\n            if step > 0:\n                size = max(0, (stop - start + step - 1) // step)\n            else:\n                size = max(0, (stop - start + step + 1) // step)\n            output_shape.append(size)","sourceCodeStart":1079,"sourceCodeEnd":1115,"githubUrl":"https://github.com/Genesis-Embodied-AI/genesis-world/blob/56e4aa5d82bdb83f2e532e4cc364cb69527acb06/genesis/utils/misc.py#L1079-L1115","documentation":"get_indexed_shape (used by assign_indexed_tensor for scatter-style indexed writes) computes the output shape of an indexing expression. Like NumPy indexing, it expands a single Ellipsis into the full slices needed to cover the tensor's ndim, but two or more Ellipses in one index tuple are ambiguous and rejected with IndexError. This mirrors torch/NumPy semantics: 'Only one ellipsis (or ':') is allowed'.","triggerScenarios":"Calling torch-style advanced indexing helpers (get_indexed_shape / assign_indexed_tensor) with an indices tuple containing Ellipsis twice, e.g. (Ellipsis, 0, Ellipsis) or building indices dynamically where a default Ellipsis is appended to a tuple that already contains one.","commonSituations":"Programmatically constructing index tuples (e.g. (env_idx, Ellipsis) plus a user-supplied suffix that itself contains ...), or refactoring code from explicit slicing into Ellipsis-based slicing and leaving a duplicate. Rare with hand-written literal indices since two ellipses are visually obvious.","solutions":["Keep exactly one Ellipsis in the index tuple; replace the redundant one with slice(None) or drop it.","When concatenating index tuples dynamically, filter to at most one Ellipsis: keep the first and expand/remove the rest.","Prefer explicit slice(None) in generated code paths where an Ellipsis might already be present upstream."],"exampleFix":"# before\nassign_indexed_tensor(dst, src, (Ellipsis, mask, Ellipsis))\n# after\nassign_indexed_tensor(dst, src, (Ellipsis, mask))","handlingStrategy":"validation","validationCode":"assert sum(1 for i in indices if i is Ellipsis) <= 1, 'multiple Ellipsis in index tuple'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When assembling index tuples dynamically, collapse duplicate Ellipsis to one.","Prefer explicit slice(None) in generated index expressions."],"tags":["genesis","indexing","ellipsis","numpy-semantics","torch"],"backgroundTag":"invalid-index-expression","analyzedSha":"56e4aa5d82bdb83f2e532e4cc364cb69527acb06","analyzedAt":"2026-08-28T15:15:07.922Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}