{"record":{"id":"7243b72605396fa7","repo":"bazelbuild/bazel","slug":"tokens-2-in-line-not-surrounded-by-bracket","errorCode":null,"errorMessage":"{tokens[2]} in {line} not surrounded by [] brackets","messagePattern":"(.+?) in (.+?) not surrounded by \\[\\] brackets","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/ctexplain/bazel_api.py","lineNumber":155,"sourceCode":"  or:\n      \"<label> (null)\"\n\n  Args:\n    line: The expected input.\n\n  Returns:\n    Corresponding ConfiguredTarget if the line matches else None.\n  \"\"\"\n  tokens = line.split(maxsplit=2)\n  label = tokens[0]\n  if tokens[1][0] != \"(\" or tokens[1][-1] != \")\":\n    raise ValueError(f\"{tokens[1]} in {line} not surrounded by parentheses\")\n  config_hash = tokens[1][1:-1]\n  if config_hash == \"null\":\n    fragments = ()\n  else:\n    if tokens[2][0] != \"[\" or tokens[2][-1] != \"]\":\n      raise ValueError(f\"{tokens[2]} in {line} not surrounded by [] brackets\")\n    # The fragments list looks like '[Fragment1, Fragment2, ...]'. Split the\n    # whole line on ' [' to get just this list, then remove the final ']', then\n    # split again on ', ' to convert it to a structured tuple.\n    fragments = tuple(line.split(\" [\")[1][0:-1].split(\", \"))\n  return ConfiguredTarget(\n      label=label,\n      config=None,  # Not yet available: we'll need `bazel config` to get this.\n      config_hash=config_hash,\n      transitive_fragments=fragments)\n\n\ndef _base_name(full_name: str) -> str:\n  \"\"\"Strips a fully qualified Java class name to the file scope.\n\n  Examples:\n    - \"A.B.OuterClass\" -> \"OuterClass\"\n    - \"A.B.OuterClass$InnerClass\" -> \"OuterClass$InnerClass\"\n","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/tools/ctexplain/bazel_api.py#L137-L173","documentation":"Companion check to error 132 in ctexplain's line parser: when the config hash is not 'null', the third token (maxsplit=2 leaves the whole remainder) must be a fragments list delimited by '[' and ']'. If it is not bracketed, this ValueError is raised with the token and line.","triggerScenarios":"A cquery line like '//pkg:target (abc123) Fragment1, Fragment2' — fragments present but without surrounding brackets — or trailing output (progress lines, warnings) captured into the parsed stream where a fragments list is expected.","commonSituations":"Bazel progress/status messages interleaved with cquery output and not filtered; bazel version changing the fragments rendering; consuming a stale captured log whose format predates bracketed fragments.","solutions":["Regenerate the cquery output being parsed, ensuring stderr/progress lines are not mixed into stdout.","Run cquery with --noshow_progress (or capture only stdout) before feeding lines to the parser.","Update _ParseConfiguredTargetLine if the bazel output format legitimately changed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def looks_like_ct_line(line):\n    toks = line.split(maxsplit=2)\n    return len(toks) >= 2 and toks[1].startswith('(') and toks[1].endswith(')') and (len(toks) < 3 or (toks[2].startswith('[') and toks[2].endswith(']')))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter progress lines out of cquery stdout before parsing (run with --noshow_progress).","Capture stdout and stderr separately when shelling out to bazel."],"tags":["ctexplain","cquery","parsing","bazel"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}