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
- Rerun with VERBOSE_COVERAGE=1 to see which entry point path failed to resolve.
- Ensure the python coverage tool target is properly configured and present in the binary's runfiles (correct coverage plugin/toolchain registration).
- 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
- Register the python coverage tool in the build so its entry point lands in runfiles.
- Use VERBOSE_COVERAGE=1 whenever triaging coverage startup problems.
- Clear COVERAGE_DIR when coverage is not intended.
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
- Bazel does not support execution of Python interpreters via
- Cannot find .runfiles directory for %s
- Could not find python binary: {PYTHON_BINARY}
- Unsupported JUnit Runner API version ${JUNIT_API_VERSION_PRO
- No filter expression specified after ${arg}
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/e036bfec5e51da2d.
Report an issue: GitHub.