{"record":{"id":"cb1522886180aacb","repo":"jax-ml/jax","slug":"tiling-self-tiles-does-not-apply-to-shape-orig","errorCode":null,"errorMessage":"Tiling {self.tiles} does not apply to shape {orig_shape}","messagePattern":"Tiling (.+?) does not apply to shape (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/mosaic/gpu/fragmented_array.py","lineNumber":93,"sourceCode":"      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):]\n      if any(s % t != 0 for s, t in zip(tiled_dims, tile)):\n        fail()\n      shape = (*untiled_dims, *(d // t for d, t in zip(tiled_dims, tile)), *tile)\n    return shape\n\n  def untile_shape(self, shape: tuple[int, ...]) -> tuple[int, ...]:\n    \"\"\"Computes the shape of an array before tiling from its tiled shape.\"\"\"\n    orig_shape = shape\n    def fail():\n      raise ValueError(\n          f\"shape {orig_shape} is not a valid result of applying tiling {self}.\"\n      )\n    for tile in reversed(self.tiles):\n      if len(tile) > len(shape):","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/mosaic/gpu/fragmented_array.py#L75-L111","documentation":"Tiling.tile_shape applies each tile to the trailing dims of the shape; it fails when a tile has more dims than remain, or the shape dims are not evenly divisible by the corresponding tile dims.","triggerScenarios":"Calling tile_shape((3, 8)) with Tiling([(4, 4)]) — 3 not divisible by 4; or tile_shape((4,)) with a rank-2 tile since len(tile) > len(shape).","commonSituations":"Applying a register layout designed for one tensor shape to a differently-shaped tensor; padding assumptions that don't hold.","solutions":["Pad or slice the array so trailing dims are multiples of the tile dims","Use a tiling whose tiles match the array's shape (smaller final tile)","Check shape lengths: the outermost (first) tile must have rank <= array rank"],"exampleFix":"// before\nTiling([(4, 4)]).tile_shape((6, 8))  # 6 % 4 != 0\n// after\nTiling([(4, 4), (2,)]).tile_shape((6, 8))  # 6 = 2*4... use tile matching shape","handlingStrategy":"validation","validationCode":"def applies(t, shape):\n    s = shape\n    for tile in t.tiles:\n        if len(tile) > len(s): return False\n        if any(x % y for x, y in zip(s[-len(tile):], tile)): return False\n        s = s[:-len(tile)] + tuple(x//y for x, y in zip(s[-len(tile):], tile))\n    return True\nassert applies(tiling, shape)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pad tensors to tile multiples before applying layouts","Keep one source of truth pairing tensor shapes with their tilings"],"tags":["mosaic","fragmented-array","tiling","shape-mismatch"],"backgroundTag":"shape-not-divisible-by-tile","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}