2.3 Hermeticity & Sandboxing

bazel build //app:server --spawn_strategy=local may work while the same target fails in a sandbox. It may also pass on one laptop, fail on CI, and look fixed after bazel clean. These outcomes call for the same investigation: what did the action really depend on, and did Bazel record it?

Trustworthy reuse needs two properties. The action's recorded inputs must match its real inputs, and equivalent executions must produce stable output bytes. Sandboxing can expose violations of the first property on the local machine. Non-determinism is the separate failure of the second.

Compare The Recorded And Real Inputs

2.3.1 Hermeticity defines input hermeticity. Source files are only part of the action's world. Tools, configuration, environment, and repository setup can also change what it does. A hidden input can create a false cache hit, so the risk is correctness rather than only lost speed.

2.3.2 Sandboxing turns that principle into execution-time evidence. Bazel runs an action in a prepared world containing the inputs it staged, not everything available on the host. When an undeclared header, tool, or file is missing from that staged view, a host-dependent action fails.

Sandboxing often turns that incomplete description into a useful failure. If switching to local makes the failure disappear, the comparison is evidence of host coupling, not usually a permanent fix. The genrule-sandbox-paths bad_relative_path target demonstrates the mistake: it hard-codes config/input.txt without declaring the file in srcs, so sandboxed execution reports cat: config/input.txt: No such file or directory while local execution happens to find the host path.

This declared-input discipline prepares actions for the strategy choices in 2.5.1 Strategies Abstraction. Switching strategies is safe only when the action does not depend on the accidental contents of one execution environment.

Separate Missing Inputs From Unstable Outputs

2.3.3 Non-Determinism Sources covers a sandbox's main limit. A tool can receive the right declared inputs and still write the current date, embed an absolute output-base path, serialize data in random order, or consult other unstable state. The sandbox completed its job, but the output bytes can still drift.

If an action is failing now, 2.3.4 First-Response Debugging Flags gives the shortest escalation path. --verbose_failures shows the failed command, --sandbox_debug preserves the sandbox for inspection, and --subcommands shows the wider execution stream. If the build succeeds but clean executions produce different artifacts or keep destabilizing reuse, investigate non-determinism before blaming the cache.

A local-only success is evidence, not a durable .bazelrc repair. Persistent strategy and environment choices belong to 2.5.2 Strategies & Mnemonics and 3.2.6 Hermeticity Settings, but the immediate goal is to model the missing input or tool.

Try the hermeticity-settings snippet to compare an undeclared host environment value with an explicitly pinned --action_env. The consuming genrule is intentionally small enough to inspect completely.

key takeaway

Hermeticity makes reuse trustworthy: the declared action must contain its real inputs, and those inputs must produce stable outputs. Sandboxing exposes missing declarations. Determinism checks the behavior that remains once the declared world is complete.