bazelbuild/bazel · error · ValueError

{tokens[2]} in {line} not surrounded by [] brackets

Error message

{tokens[2]} in {line} not surrounded by [] brackets

What it means

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.

Source

Thrown at tools/ctexplain/bazel_api.py:155

  or:
      "<label> (null)"

  Args:
    line: The expected input.

  Returns:
    Corresponding ConfiguredTarget if the line matches else None.
  """
  tokens = line.split(maxsplit=2)
  label = tokens[0]
  if tokens[1][0] != "(" or tokens[1][-1] != ")":
    raise ValueError(f"{tokens[1]} in {line} not surrounded by parentheses")
  config_hash = tokens[1][1:-1]
  if config_hash == "null":
    fragments = ()
  else:
    if tokens[2][0] != "[" or tokens[2][-1] != "]":
      raise ValueError(f"{tokens[2]} in {line} not surrounded by [] brackets")
    # The fragments list looks like '[Fragment1, Fragment2, ...]'. Split the
    # whole line on ' [' to get just this list, then remove the final ']', then
    # split again on ', ' to convert it to a structured tuple.
    fragments = tuple(line.split(" [")[1][0:-1].split(", "))
  return ConfiguredTarget(
      label=label,
      config=None,  # Not yet available: we'll need `bazel config` to get this.
      config_hash=config_hash,
      transitive_fragments=fragments)


def _base_name(full_name: str) -> str:
  """Strips a fully qualified Java class name to the file scope.

  Examples:
    - "A.B.OuterClass" -> "OuterClass"
    - "A.B.OuterClass$InnerClass" -> "OuterClass$InnerClass"

View on GitHub (pinned to e6e199d060)

Solutions

  1. Regenerate the cquery output being parsed, ensuring stderr/progress lines are not mixed into stdout.
  2. Run cquery with --noshow_progress (or capture only stdout) before feeding lines to the parser.
  3. Update _ParseConfiguredTargetLine if the bazel output format legitimately changed.
Defensive patterns

Strategy: validation

Validate before calling

def looks_like_ct_line(line):
    toks = line.split(maxsplit=2)
    return len(toks) >= 2 and toks[1].startswith('(') and toks[1].endswith(')') and (len(toks) < 3 or (toks[2].startswith('[') and toks[2].endswith(']')))

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/7243b72605396fa7. Report an issue: GitHub.