Safeguard
Developer Tools•

Which Bazel lockfile mode should CI use: update or error?

Bazel's lockfile_mode flag has four settings. Use error in CI so a changed dependency graph fails the build instead of silently rewriting the lockfile.

Safeguard Security Team
4 min read

Use the error mode in CI. It fails the build if anything consulted during module resolution is missing or out of date, and it never rewrites the lockfile or makes network requests during resolution. Keep the default update mode for developers, and let a reviewed pull request change the lockfile.

The four modes

Bazel records the result of module resolution in MODULE.bazel.lock. The lockfile_mode flag decides what Bazel does when the project differs from that file.

ModeBehaviorGood for
update (default)Uses lockfile data to skip known downloads, adds missing informationLocal development
refreshLike update, but refreshes mutable data such as yanked versions, roughly hourlyA scheduled job that checks for newly yanked modules
errorFails if information is missing or out of date, no changes, no resolution network requestsCI and release builds
offLockfile neither checked nor updatedDebugging only

Module extensions that mark themselves reproducible may still make network requests in error mode, but they are expected to produce the same result every time.

Why CI should fail on drift

In update mode, a build can quietly change the lockfile. If CI runs that way and nobody commits the result, you get a build that differs from what a reviewer saw. In error mode the drift becomes a red build, which is a signal a human can act on.

The lockfile holds hashes of every remote registry file used in resolution, plus the inputs and outputs of each module extension. A lockfile change in a pull request is therefore a readable record of what your graph is about to consume.

A workable setup

  1. Commit MODULE.bazel.lock to version control. The Bazel docs list this as a best practice.
  2. Pin the Bazel version with a version file and a launcher, because the lockfile is specific to the Bazel version and can change even between compatible releases.
  3. In CI, run builds with the error mode set.
  4. Use the tidy command in a dedicated dependency update job that opens a pull request with the lockfile diff.
  5. Add a scheduled job in refresh mode to notice newly yanked versions without touching developer builds.
# .bazelrc
common:ci --lockfile_mode=error

What the lockfile does not give you

It does not list your packages in a scanner friendly format, and it only includes dependencies in the invocation that produced it. It also does not decide whether a module is safe. Treat it as proof that resolution was repeatable, then feed a proper inventory to your scanner.

Merge conflicts

The format is designed to limit conflicts, and Bazel documents a custom git merge driver. For other conflicts, restore the previous lockfile, fix MODULE.bazel, and regenerate with the deps command rather than hand editing.

Where Safeguard fits

Safeguard can inventory the dependencies your repository declares through SBOM and dependency scanning, and reachability analysis helps you decide which findings matter first. You can try a free scan on a repository to see what it finds. Check coverage for your specific build files before relying on it.

Quick check

Can the error mode ever change my lockfile?

No. It never changes the lockfile. A lockfile that passes in this mode may still be rewritten, pruned of superfluous entries, by update mode later.

Is the lockfile enough to scan my dependencies?

Not on its own. It records resolution results and hashes, not a package inventory. See the post on scanning dependencies in a Bazel repository.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.