bazelbuild/bazel · error · EnvironmentError

Python coverage tool %r not found. Try running with VERBOSE_

Error message

Python coverage tool %r not found. Try running with VERBOSE_COVERAGE=1 to collect more information.

What it means

Raised by the Python launcher when coverage is enabled (COVERAGE_DIR set), a coverage entry point was resolved via runfiles, but that resolved path does not exist on disk (EnvironmentError/OSError). The message suggests VERBOSE_COVERAGE=1 to trace how the entry point was found.

Source

Thrown at tools/python/python_bootstrap_template.txt:517

  program = python_program = FindPythonBinary(module_space)
  if python_program is None:
    raise AssertionError('Could not find python binary: ' + PYTHON_BINARY)

  # COVERAGE_DIR is set if coverage is enabled and instrumentation is configured
  # for something, though it could be another program executing this one or
  # one executed by this one (e.g. an extension module).
  if os.environ.get('COVERAGE_DIR'):
    cov_tool = FindCoverageEntryPoint(module_space)
    if cov_tool is None:
      PrintVerboseCoverage('Coverage was enabled, but python coverage tool was not configured.')
    else:
      # Inhibit infinite recursion:
      if 'PYTHON_COVERAGE' in os.environ:
        del os.environ['PYTHON_COVERAGE']

      if not os.path.exists(cov_tool):
        raise EnvironmentError(
          'Python coverage tool %r not found. '
          'Try running with VERBOSE_COVERAGE=1 to collect more information.'
          % cov_tool
        )

      # coverage library expects sys.path[0] to contain the library, and replaces
      # it with the directory of the program it starts. Our actual sys.path[0] is
      # the runfiles directory, which must not be replaced.
      # CoverageScript.do_execute() undoes this sys.path[0] setting.
      #
      # Update sys.path such that python finds the coverage package. The coverage
      # entry point is coverage.coverage_main, so we need to do twice the dirname.
      python_path_entries = new_env['PYTHONPATH'].split(os.pathsep)
      python_path_entries.append(os.path.dirname(os.path.dirname(cov_tool)))
      new_env['PYTHONPATH'] = os.pathsep.join(Deduplicate(python_path_entries))
  else:
    cov_tool = None

View on GitHub (pinned to e6e199d060)

Solutions

  1. Rerun with VERBOSE_COVERAGE=1 to see which entry point path failed to resolve.
  2. Ensure the python coverage tool target is properly configured and present in the binary's runfiles (correct coverage plugin/toolchain registration).
  3. Unset COVERAGE_DIR if coverage was not intended for this run.

Example fix

# before
COVERAGE_DIR=/tmp/cov ./my_binary  # coverage tool absent from runfiles

# after
unset COVERAGE_DIR && ./my_binary  # or fix coverage tool registration, then:
# VERBOSE_COVERAGE=1 bazel coverage //my:target
Defensive patterns

Strategy: validation

Validate before calling

import os
cov = os.environ.get('PYTHON_COVERAGE')
if os.environ.get('COVERAGE_DIR') and cov:
    assert os.path.exists(cov), 'coverage entry point %r missing from runfiles' % cov

Prevention

When it happens

Trigger: COVERAGE_DIR is set in the environment and the configured python coverage tool's runfiles path resolves to a location with no actual file — stale runfiles, a coverage tool target not built, or a manually set PYTHON_COVERAGE pointing at a missing script.

Common situations: Running bazel coverage where the coverage tool target was not included in the runfiles; leftover COVERAGE_DIR from a previous CI step; mixing python2/python3 coverage entry points after an interpreter migration.

Related errors


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