Skip to content
Latchkey

Bazel "undeclared output" from an action in CI

A Bazel action must declare every file it writes. When an action writes a file the rule never declared, or fails to write a file it did declare, Bazel rejects the action and names the mismatched output.

What this error means

A genrule or custom rule fails with "declared output ... was not created by genrule" or an action reports an output file it wrote that was not declared.

bazel
ERROR: /home/runner/work/app/app/foo/BUILD.bazel:2:8: declared output
'foo/out.txt' was not created by genrule. This is probably because the genrule
actually didn't create this output, or because the output was a directory and the
genrule was run remotely.

Common causes

The command did not write the declared file

The genrule cmd produced a different filename or path than the one listed in outs, so the declared output is missing.

The output is a directory or written outside the sandbox

Actions must write declared files, not directories, and only inside the action output tree; anything else is undeclared.

How to fix it

Match the command output to the declared outs

  1. Confirm the cmd writes to the exact path in outs using $@ or $(location ...).
  2. Declare a directory output with a rule that supports it if you truly emit a tree.
  3. Re-run so the produced file matches the declaration.
foo/BUILD.bazel
genrule(
    name = "gen",
    outs = ["out.txt"],
    cmd = "echo hello > $@",
)

Use location expansion for output paths

Reference outputs through $(location) so the command always targets the declared path Bazel expects.

foo/BUILD.bazel
cmd = "generate > $(location out.txt)"

How to prevent it

  • Declare exactly the files an action writes, no more and no less.
  • Use $@ or $(location ...) so output paths match declarations.
  • Avoid writing directories or files outside the action output tree.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →