{"record":{"id":"ea2201912979cbb4","repo":"jax-ml/jax","slug":"tiles-must-have-a-decreasing-rank","errorCode":null,"errorMessage":"Tiles must have a decreasing rank","messagePattern":"Tiles must have a decreasing rank","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/mosaic/gpu/fragmented_array.py","lineNumber":79,"sourceCode":"  to the rank of the tile) is unfolded into two dimensions: first equal to the\n  ratio of the dimension size and the tile size, and second equal to the tile\n  size. Then, all newly unfolded minor dimensions are transposed to appear at\n  the end.\n\n  This expression describes multi-level tiling, by applying each element of\n  `tiles` in sequence to the array.\n\n  See https://openxla.org/xla/tiled_layout for a more detailed explanation.\n  \"\"\"\n  tiles: tuple[tuple[int, ...], ...]\n\n  def __post_init__(self):\n    if not self.tiles:\n      return\n    last_tile_rank = len(self.tiles[0])\n    for tile in self.tiles:\n      if len(tile) > last_tile_rank:\n        raise ValueError(\"Tiles must have a decreasing rank\")\n      if not tile:\n        raise ValueError(\"Tiles must not be empty\")\n      if any(d <= 0 for d in tile):\n        raise ValueError(f\"Tile shape must only have positive sizes, got: {self.tiles}\")\n      last_tile_rank = len(tile)\n\n  def __str__(self):\n    return f\"Tiling({''.join(map(str, self.tiles))})\"\n\n  def tile_shape(self, shape: tuple[int, ...]) -> tuple[int, ...]:\n    \"\"\"Computes the shape of an array after tiling.\"\"\"\n    orig_shape = shape\n    def fail():\n      raise ValueError(f\"Tiling {self.tiles} does not apply to shape {orig_shape}\")\n    for tile in self.tiles:\n      if len(tile) > len(shape):\n        fail()\n      untiled_dims, tiled_dims = shape[:-len(tile)], shape[-len(tile):]","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/mosaic/gpu/fragmented_array.py#L61-L97","documentation":"Tiling is a list of tile tuples where each successive tile must apply to no more dims than the previous one (non-increasing rank). This validation in Tiling.__post_init__ rejects configurations like [(2,), (4, 4)] after [(4, 4), (2,)].","triggerScenarios":"Constructing fragmented_array.Tiling with tiles whose ranks increase, e.g. Tiling([(2, 2), (4,) , (8, 8)]) — the inner (nested) tiles must have rank <= the outer ones.","commonSituations":"Hand-writing nested tilings for register layouts; converting a layout spec where tile order got reversed.","solutions":["Order tiles outermost-first with non-increasing rank, e.g. [(8, 8), (4,), (2,)]","Build tilings via layout constructors (e.g. fa.TiledLayout) rather than literal tuples","Remember the first tile is the outermost covering the most dims"],"exampleFix":"// before\nTiling([(2,), (8, 8)])\n// after\nTiling([(8, 8), (2,)])","handlingStrategy":"validation","validationCode":"ranks = [len(t) for t in tiles]\nassert all(ranks[i] >= ranks[i+1] for i in range(len(ranks)-1)), 'tile ranks must be non-increasing'","typeGuard":"def is_valid_tiling_order(tiles) -> bool:\n    return all(len(tiles[i]) >= len(tiles[i+1]) for i in range(len(tiles)-1))","tryCatchPattern":null,"preventionTips":["Use fa.TiledLayout constructors instead of raw tile tuples","Remember: first tile is outermost, ranks must never increase"],"tags":["mosaic","fragmented-array","tiling","layout","validation"],"backgroundTag":"invalid-layout-spec","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}