{"record":{"id":"fd5379cd0d301712","repo":"jax-ml/jax","slug":"symbolicscope-constraint-must-be-a-string-got-re","errorCode":null,"errorMessage":"SymbolicScope constraint must be a string: got {repr(c_str)}","messagePattern":"SymbolicScope constraint must be a string: got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/export/shape_poly.py","lineNumber":1046,"sourceCode":"\n    for c_str in constraints_str:\n      self._parse_and_process_explicit_constraint(c_str)\n      self._bounds_cache.clear()\n    self._initialized = True\n\n  def __str__(self) -> str:\n    extras = []\n    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)","sourceCodeStart":1028,"sourceCodeEnd":1064,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/export/shape_poly.py#L1028-L1064","documentation":"Each explicit symbolic constraint must be an individual string like 'a*2 == b'. This error fires when a non-string element (int, tuple, None) ends up in the constraints sequence during parsing.","triggerScenarios":"SymbolicScope([None]), constraints=[('n','>=',4)] (pre-parsed tuples), or dynamically built constraint lists that accidentally include non-string entries.","commonSituations":"Programmatically assembling constraints where one branch appends a tuple or an f-string's arguments instead of the f-string result.","solutions":["Flatten/convert every constraint to a single formatted string before constructing the scope","Add an assert all(isinstance(c, str) for c in constraints) before the call","Fix the generator expression that produced non-string entries"],"exampleFix":"# before\nconstraints = [('n', '>=', 4)]\n# after\nconstraints = [f'{a} {op} {b}' for a, op, b in [('n', '>=', 4)]]","handlingStrategy":"validation","validationCode":"assert all(isinstance(c, str) for c in constraints), constraints","typeGuard":"def all_str_constraints(cs) -> bool:\n    return all(isinstance(c, str) for c in cs)","tryCatchPattern":null,"preventionTips":["Build constraint lists with f-strings, not tuples of parts","Unit-test constraint generation helpers"],"tags":["jax","shape-polymorphism","constraints","type-validation"],"backgroundTag":"invalid-constraint-format","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}