{"record":{"id":"e7dd1d7def552f78","repo":"jax-ml/jax","slug":"constraint-parsing-error-must-contain-one-of","errorCode":null,"errorMessage":"Constraint parsing error: must contain one of '==' or '>=' or '<='","messagePattern":"Constraint parsing error: must contain one of '==' or '>=' or '<='","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/export/shape_poly.py","lineNumber":1054,"sourceCode":"    if self._explicit_constraints:\n      extras.append(\" with constraints:\")\n      for constr in self._explicit_constraints:\n        extras.append(f\"  {constr.debug_str}\")\n    loc = source_info_util._summarize_frame(self._location_frame) if self._location_frame else \"unknown\"\n    return f\"{id(self)} created at {loc}\" + \"\\n\".join(extras)\n  __repr__ = __str__\n\n  def _parse_and_process_explicit_constraint(self, c_str: str):\n    if not isinstance(c_str, str):\n      raise ValueError(\n          f\"SymbolicScope constraint must be a string: got {repr(c_str)}\")\n    cmp_pos, cmp, is_geq = c_str.find(\"==\"), Comparator.EQ, True\n    if cmp_pos < 0:\n      cmp_pos, cmp, is_geq = c_str.find(\">=\"), Comparator.GEQ, True\n      if cmp_pos < 0:\n        cmp_pos, cmp, is_geq = c_str.find(\"<=\"), Comparator.GEQ, False\n      if cmp_pos < 0:\n        raise ValueError(\"Constraint parsing error: must contain one of '==' or '>=' or '<='\")\n    e1_str = c_str[:cmp_pos]\n    e1, = _Parser(e1_str, None, repr(e1_str), self).parse()\n    e2_str = c_str[cmp_pos + 2:]\n    e2, = _Parser(e2_str, None, repr(e2_str), self).parse()\n    if cmp == Comparator.GEQ and not is_geq:\n      e1, e2 = e2, e1\n\n    # Compute e1 - e2 before we add to normalization rules\n    constr = _SymbolicConstraint(debug_str=c_str, cmp=cmp, e1=e1, e2=e2,\n                                 diff=e1 - e2)\n    self._process_explicit_constraint(constr)\n\n  def _process_explicit_constraint(self, constr: _SymbolicConstraint):\n    if (diff_const := _DimExpr._to_constant(constr.diff)) is not None:\n      if ((constr.cmp == Comparator.EQ and diff_const != 0) or\n          (constr.cmp == Comparator.GEQ and diff_const < 0)):\n        raise ValueError(f\"Unsatisfiable explicit constraint: {constr.debug_str}\")\n      return","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/export/shape_poly.py#L1036-L1072","documentation":"A constraint string must contain exactly one of the comparison tokens '==', '>=' or '<='. If none of these substrings is found, the parser cannot split it into two sides and raises ValueError.","triggerScenarios":"Constraints like 'n > 4' (strict inequality, unsupported), 'n = 4', 'n 4', or 'max(n, 4)' with no comparator.","commonSituations":"Typos in constraint strings; assuming strict > or < is supported (only >=/<=/== are); copying Python syntax like 'n != 4'.","solutions":["Use only '==', '>=', '<=' in constraint strings; rewrite 'n > 4' as 'n >= 5' for integers","Fix typos ('=>' -> '>=', '=' -> '==')","Validate each constraint contains a supported token before constructing the scope"],"exampleFix":"# before\nconstraints = ('n > 4',)\n# after\nconstraints = ('n >= 5',)  # strict inequalities not supported","handlingStrategy":"validation","validationCode":"import re\nassert all(re.search(r'(==|>=|<=)', c) for c in constraints), 'need ==, >=, or <='","typeGuard":"def well_formed_constraint(c: str) -> bool:\n    return isinstance(c, str) and any(t in c for t in ('==','>=','<='))","tryCatchPattern":null,"preventionTips":["Remember strict > and < are unsupported; use >= / <=","Automate the comparator check in test fixtures"],"tags":["jax","shape-polymorphism","constraints","parsing"],"backgroundTag":"invalid-constraint-format","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}