5.2.4 bazel config — Configuration Inspection
extracquery tells you which configuration a configured target uses. bazel config opens that configuration and shows the option values inside it. Together
they turn an opaque suffix such as (3a0f53e) into evidence you can compare
with a config_setting or a transition.1
The command is an experimental, unsupported diagnostic interface in Bazel 9.0, so treat its text layout and Java fragment names as human-readable debugging output, not a stable API for production tooling.2
Preserve the configuration you want to inspect
bazel config does not reconstruct an arbitrary historical configuration from
its hash. It looks for configuration objects still present in the current Bazel
server's Skyframe cache.2 Generate the configured graph first, then inspect
it immediately:
bazel cquery 'deps(//app:server)' --platforms=//platforms:linux
//app:server (3a0f53e)
//app:linux_runtime (3a0f53e)
...
@@platforms//host:host (3030ed4)
This example comes from the runnable select-errors
snippet. Its
select() chooses the
Linux runtime under the requested target platform. The short hexadecimal text
in parentheses is a configuration ID. It identifies the configuration attached
to that result. It is not a label and should not be interpreted as an action or
remote-cache key.
Pass that ID to config, keeping the build options from the cquery invocation:
bazel config 3a0f53e --platforms=//platforms:linux
The repeated option is operationally important. Changing the command-line
options can invalidate the cached configuration nodes before config reads
them. Bazel's official debugging guidance therefore says to invoke both commands
with the same flags.1 In a real repository, that includes the named configs
and other build options that established the context, not just the one flag that
looks relevant.
With no ID, bazel config lists the configurations currently available in the
server. This is useful when output has scrolled away or when you want the full
ID behind a short prefix:
bazel config --platforms=//platforms:linux
Available configurations:
...
3030ed4c810cf3435d066294fa495e650fe75173e4b4ef410ea56cb683458569 fastbuild-noconfig (test-trimmed)
3a0f53e6285b4e814e79d042cc4be4b18d31f67188527ee2e25f4e2cc5981c68 k8-fastbuild (test-trimmed)
The exact IDs and mnemonic descriptions depend on the workspace, host, flags, and Bazel version. Use them only as identifiers from your own invocation.
Find the value that decides a select()
Text output groups values into configuration fragments and fragment-option classes. The implementation-shaped headings are less important than the option names and values beneath them. For the example above, the relevant entry is:
FragmentOptions com.google.devtools.build.lib.analysis.PlatformOptions {
platforms: [//platforms:linux]
...
}
Read the output against the condition you are debugging:
- Use
cqueryin the real top-level context to obtain the configured target instance, as described in 5.2.2bazel cquery— Configured Graph. - Inspect that instance's configuration ID with the same flags.
- Find the built-in option,
--definevalue, platform selection, or user-defined Starlark flag referenced by the candidateconfig_setting. - Compare the value with every requirement of that condition. A
config_settingmatches only when all of its specified requirements match.1
This separates two questions that are easy to blur. cquery proves which branch
and dependency edge Bazel selected. bazel config shows the values that the
condition was evaluated against. 3.3.1 Configurable Attributes (select()) defines the matching rules in
depth.
For scripts or focused inspection, Bazel 9.0 also accepts --output=json:
bazel config 3a0f53e --platforms=//platforms:linux --output=json
The JSON separates metadata such as configHash, mnemonic, and isExec from
fragment options and the user-defined options map.2 This is preferable to
scraping Java class headings from the text form, but the command itself remains
experimental and unsupported.
Diff configurations before blaming a transition
When the same label occurs in two configurations, pass both IDs. Bazel prints the option differences instead of two full dumps:2
bazel config <first_id> <second_id> <the same build flags>
This is the fastest way to reduce “why is this dependency configured twice?” to
a concrete set of differences. For a Starlark transition, first use
cquery --transitions=lite to locate the edge, then diff the configurations on
the two sides. If the changed options agree with the transition's declared
outputs, the transition is behaving as specified. If an expected change is
missing or an unexpected one appears, inspect the transition implementation
described in 4.7.2 Starlark Transitions.
Do not assume every line in a large diff was directly written by that
transition. Configurations can also differ because of exec transitions,
4.6.3 Toolchain Resolution, platform selection, option defaults, trimming,
or other transitions along the path. Use the graph edge from cquery to
establish provenance, then use the config diff to inspect state.
Keep the investigation narrow: identify two configured target instances on one specific path, preserve their exact invocation flags, and diff those two IDs. Dumping every available configuration produces plenty of data but little causal evidence.
Know when to switch tools
bazel config explains configuration state. It does not explain the rc-file
layers that supplied command-line options. Use --announce_rc and
3.2.1 .bazelrc Hierarchy for that. It also does not show the final compiler or
linker command generated from those values. Use 5.2.3 bazel aquery — Action Graph for the action
plan.
If config reports that an ID cannot be found, rerun the producing cquery and
then config without changing flags or server state. A shutdown, an invocation
whose options invalidate analysis state, or simply inspecting an ID from a
different output base leaves no cached object for this command to display.1
Use bazel config immediately after cquery, with the same build flags, to turn
a configured target's ID into inspectable option values. Compare those values
with config_setting requirements to explain a select(), or pass two IDs to
isolate configuration differences around a transition. The command reads the
current server's Skyframe cache and remains experimental in Bazel 9.0, so its
output is diagnostic evidence rather than a stable automation contract.
Check your understanding · 4 questions
1.A developer saves a configuration ID from yesterday, restarts Bazel, and runs bazel config with that ID. Bazel cannot find it. What should the developer do?
Select one answer
2.A cquery run used --config=ci --platforms=//platforms:linux. Which practices help keep its configuration available for the following bazel config inspection?
Select all that apply
3.The same label appears under two configuration IDs after a suspected Starlark transition, and a select() chose an unexpected branch. What is the strongest next diagnostic step?
Select one answer
4.Match each investigation to the tool that answers it most directly:
Drag each answer onto the matching prompt, or click an answer and then click a prompt
select() branch did Bazel choose?Footnotes
-
Configurable build attributes — the
cqueryplusbazel configdebugging workflow, configuration-cache requirement, matching semantics, and same-flags warning ↩1 ↩2 ↩3 ↩4 -
Command-Line Reference — Bazel 9.0
configcommand syntax, zero/one/two-ID modes, diff behavior, JSON output, and experimental status ↩1 ↩2 ↩3 ↩4