{"record":{"id":"d856370633ceab17","repo":"jax-ml/jax","slug":"symbolic-dimension-comparison-cmp-str-is-incon","errorCode":null,"errorMessage":"Symbolic dimension comparison {cmp_str()} is inconclusive.{describe_scope}","messagePattern":"Symbolic dimension comparison (.+?) is inconclusive\\.(.+?)","errorType":"exception","errorClass":"InconclusiveDimensionOperation","httpStatus":null,"severity":"error","filePath":"jax/_src/export/shape_poly.py","lineNumber":1199,"sourceCode":"  if isinstance(e1, _DimExpr):\n    scope = e1.scope\n    if isinstance(e2, _DimExpr):\n      scope._check_same_scope(e2, f\"when comparing {cmp_str()}\")\n  elif isinstance(e2, _DimExpr):\n    scope = e2.scope\n  else:\n    return int(e1) >= int(e2)\n  lb, ub = _bounds_decision(e1 - e2, BoundsPrecision.FOR_GEQ0_OR_LT0)\n  if lb >= 0:\n    return True\n  if ub < 0:\n    return False\n\n  if scope._explicit_constraints:\n    describe_scope = f\"\\nUsing symbolic scope {scope}\"\n  else:\n    describe_scope = \"\"\n  raise InconclusiveDimensionOperation(\n      f\"Symbolic dimension comparison {cmp_str()} is inconclusive.{describe_scope}\")\n\ncore.pytype_aval_mappings[_DimExpr] = _DimExpr._get_aval\ndtypes.register_weak_scalar_type(_DimExpr)\n\ndef _convertible_to_int(p: Any) -> TypeGuard[SupportsIndex]:\n  try:\n    op.index(p)\n    return True\n  except:\n    return False\n\ndef _ensure_poly(p: DimSize,\n                 operation_name: str,\n                 scope: SymbolicScope) -> _DimExpr:\n  if isinstance(p, _DimExpr):\n    scope._check_same_scope(p, when=f\"for operation {operation_name}\")\n    return p","sourceCodeStart":1181,"sourceCodeEnd":1217,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/export/shape_poly.py#L1181-L1217","documentation":"JAX needed to decide whether one symbolic dimension is <, <=, ==, >= or > another, but the known constraints do not imply the answer either way. Symbolic comparisons are only resolved when provable, so an unconstrained comparison raises InconclusiveDimensionOperation.","triggerScenarios":"Comparisons like n < m for independent symbolic vars during export; assertions on shapes (x.shape[0] == y.shape[0] with unrelated vars); broadcasting decisions that need ordering of symbolic dims.","commonSituations":"Branching on shape relationships inside traced code (if x.shape[0] > 1), padding/valid-checking logic, or eager vs. polymorphic export where a comparison that is constant for concrete shapes becomes symbolic.","solutions":["Add explicit constraints to the SymbolicScope (e.g. 'n <= m', 'n >= 1') so the comparison becomes provable","Restructure code to avoid comparing symbolic dims (use jnp.where / lax.select on values, not shapes)","Make the compared dimension concrete by removing it from polymorphic_shapes"],"exampleFix":"# before\nout = jnp.where(x.shape[0] >= 8, f(x), g(x))  # symbolic n >= 8 inconclusive\n# after\nconstraints = ('n >= 8',)\nexp = jax.export.export(shapes('n,'), constraints=constraints)(fn)","handlingStrategy":"try-catch","validationCode":"# predeclare all needed orderings as constraints\nconstraints = tuple(f'{a} <= {b}' for a, b in known_orderings) + tuple(f'{v} >= 1' for v in vars)","typeGuard":null,"tryCatchPattern":"from jax._src.export import shape_poly\ntry:\n    branch = x.shape[0] >= 8\nexcept shape_poly.InconclusiveDimensionOperation:\n    branch = default_branch()  # restructure or add constraint","preventionTips":["Avoid host-side branching on symbolic shape comparisons","Declare order/bounds as explicit constraints up front"],"tags":["jax","shape-polymorphism","comparison","inconclusive"],"backgroundTag":"symbolic-dimension-inconclusive-operation","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}