{"record":{"id":"fae4f5153c04949f","repo":"jax-ml/jax","slug":"select-and-gather-add-tangents-and-operand-shapes","errorCode":null,"errorMessage":"select_and_gather_add tangents and operand shapes must match, got {} and {}.","messagePattern":"select_and_gather_add tangents and operand shapes must match, got (.+?) and (.+?)\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"jax/_src/lax/windowed_reductions.py","lineNumber":888,"sourceCode":"    partial(_select_and_scatter_add_impl, expand_padding=False),\n    multiple_results=False))\n# TODO(b/161704903): workaround for XLA/CPU crash.\nmlir.register_lowering(select_and_scatter_add_p, mlir.lower_fun(\n    partial(_select_and_scatter_add_impl, expand_padding=True),\n    multiple_results=False), platform='cpu')\n# TODO(b/182390722): workaround for XLA/GPU crash.\nmlir.register_lowering(select_and_scatter_add_p, mlir.lower_fun(\n    partial(_select_and_scatter_add_impl, expand_padding=True),\n    multiple_results=False), platform='gpu')\n\n\ndef _select_and_gather_add_shape_rule(\n    tangents, operand, *, select_prim, window_dimensions, window_strides,\n    padding, base_dilation, window_dilation):\n  if tangents.shape != operand.shape:\n    msg = (\"select_and_gather_add tangents and operand shapes must match, \"\n           \"got {} and {}.\")\n    raise TypeError(msg.format(tangents.shape, operand.shape))\n  return _common_reduce_window_shape_rule(\n      operand, window_dimensions, window_strides, padding, base_dilation,\n      window_dilation)\n\ndef _select_and_gather_add_sharding_rule(\n    tangents, operand, *, select_prim, window_dimensions, window_strides,\n    padding, base_dilation, window_dilation):\n  if tangents.sharding != operand.sharding:\n    raise core.ShardingTypeError(\n        \"select_and_gather_add tangents and operand shardings must match, \"\n        f\"got {tangents.sharding} and {operand.sharding}.\")\n  return reduce_window_sharding_rule(\n      operand, window_dimensions, window_strides, padding, base_dilation,\n      window_dilation)\n\ndef _select_and_gather_add_lowering(\n    ctx: mlir.LoweringRuleContext,\n    tangents, operand, *, select_prim,","sourceCodeStart":870,"sourceCodeEnd":906,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/lax/windowed_reductions.py#L870-L906","documentation":"The VJP transpose rule for select_and_gather (the max/min pooling gradient) requires the cotangent (tangents) array to have exactly the same shape as the operand. This internal rule fires during jax.grad of pooling when shapes drift.","triggerScenarios":"Applying jax.grad through max_pool where the incoming cotangent shape differs from the pooled input's shape (e.g. custom pooling wrapper reshapes between pool and loss).","commonSituations":"Custom pooling implementations that reshape or slice the operand inside the differentiable path; mismatched padding making output shapes inconsistent.","solutions":["Ensure the cotangent produced matches the operand shape; avoid reshapes between pooling and downstream ops","Use standard pooling APIs (e.g. jax.lax.reduce_window_max) whose transpose rules keep shapes aligned","Check padding config so forward output shape matches what the loss produces"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"assert tangents.shape == operand.shape","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid reshaping between pooling and loss in differentiable paths","Use standard pooling APIs"],"tags":["jax","autodiff","vjp","pooling","shape-validation"],"backgroundTag":"jax-autodiff-shape-mismatch","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}