Skip to content

fix(bazelrc): make undefined-config error self-explanatory#1131

Draft
gregmagolan wants to merge 1 commit into
mainfrom
fix-undefined-config-error-message
Draft

fix(bazelrc): make undefined-config error self-explanatory#1131
gregmagolan wants to merge 1 commit into
mainfrom
fix-undefined-config-error-message

Conversation

@gregmagolan

@gregmagolan gregmagolan commented May 25, 2026

Copy link
Copy Markdown
Member

Before

→ ⚙ Setup · Authenticating and creating CI status checks
INFO: GitHub API throttle — Aspect Workflows GitHub App: factor=13× (quota=9% used, elapsed=0s)
error: Traceback (most recent call last):
  File <builtin>, in <module>
  * /home/runner/.cache/aspect/axl/deps/.../aspect/test.axl:13, in _impl
      return run_bazel_task(ctx, command = "test")
  * /home/runner/.cache/aspect/axl/deps/.../aspect/lib/bazel_runner.axl:262, in run_bazel_task
      rc_startup_flags, flags = rc.expand_all(command = command)
error: undefined config 'ci' for command 'test'
   --> /home/runner/.cache/aspect/axl/deps/.../aspect/lib/bazel_runner.axl:262:31
    |
262 |     rc_startup_flags, flags = rc.expand_all(command = command)
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

After

(rendered with ANSI colors on a TTY/CI; bold sections + red bazelrc: not shown in the markdown below)

→ 🎬 Running `test` task
error: bazelrc: --config=ci is not defined for command 'test'

  Aspect CLI parses .bazelrc files and resolves --config= flags like Bazel.

  Bazel workspace root:
    /Users/greg/aspect/aspect-cli

  Loaded .bazelrc files:
    /Users/greg/aspect/aspect-cli/.bazelrc
    /Users/greg/aspect/aspect-cli/bazel/defaults.bazelrc
    /Users/greg/.bazelrc

  Applicable rc state for 'test' (same as --announce-rc):
    ./.bazelrc
      common  --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 ...

    ./bazel/defaults.bazelrc
      common    --nobuild_runfile_links --enable_platform_specific_config ...
      common:ci --announce_rc --color=yes --curses=yes ...

    /Users/greg/.bazelrc
      common:ext-cache  --remote_accept_cached --remote_upload_local_results
      ...

    client  --isatty=1 --config=ci --build_metadata=ASPECT_TASK_NAME=Test ...

  Try one of:
    - Add `common:ci ...` (or `build:ci`, `test:ci`) to a loaded .bazelrc
    - Don't set --config=ci

Bazel itself has hard-errored on undefined --config= since 0.16.0; bazel#7116 (request for a tolerant mode) is closed won't-fix.


The undefined config 'ci' for command 'test' error rendered with no further context, fired late in the task lifecycle (after task_started had already created CI status checks and authenticated with GitHub), and the wrapping AXL traceback made it read like an internal Aspect crash rather than a bazelrc resolution issue users could fix themselves.

Five coordinated fixes:

1. Validate bazelrc before lifecycle hooks. Flag aggregation, parse_rc, and expand_all now run before setup_phase / task_started in bazel_runner.axl. An rc-resolution error fails with no CI side effects — no status checks created, no API calls burned.

2. Enrich the error message. The block leads with a bazelrc: prefix, surfaces the Bazel workspace root (so sub-workspace anchor mismatches are visible — parent config.axl sets --config=ci while the inner .bazelrc doesn't define :ci), lists the loaded rc files, and inlines the --announce-rc view for the failing command. For rc-file references it also names the file that owns the unresolved --config=X line.

3. ANSI colors + bold headers. Matching the SGR conventions used in axl-runtime/src/eval/multi_phase.rs: bold red for the bazelrc: prefix, bold for section headers, dim for the subsystem-intro line. Color detection lives in the new axl-runtime::term module — single source of truth for the AXL runtime, the task lifecycle headers, and the bazelrc error block. Honors the NO_COLOR convention (disable iff present and non-empty); AXL-side lib/environment.axl::color_enabled does the same.

4. Strip the AXL traceback. The error is propagated through anyhow without losing its BazelRcError type; EvalError's Display renders pre-shaped user errors via starlark::Error::without_diagnostic() and main.rs switches from {err:?} to {err} when EvalError::is_pre_shaped_user_error() returns true. Non-bazelrc errors keep the full Starlark diagnostic so AXL/Aspect authors can debug.

5. Workspace-relative paths in announce(). In-tree rc files render as ./bazel/defaults.bazelrc; external files (e.g. ~/.bazelrc) keep their absolute path.


Changes are visible to end-users: yes

  • Searched for relevant documentation and updated as needed: no — error text only
  • Breaking change: no
  • Suggested release notes appear below: yes

Suggested release notes

  • The undefined config '<name>' for command '<cmd>' error from aspect build / aspect test now fails before any lifecycle hooks fire (no stuck CI status check, no wasted API calls) and expands into a Bazel-style colored explanation: the Bazel workspace root, the loaded .bazelrc files with their workspace-relative or absolute paths, an inline --announce-rc view, and suggested fixes. The AXL traceback is stripped for these errors. ANSI colors honor the NO_COLOR convention. Sub-workspace anchor mismatches (parent config.axl setting --config=ci while the inner workspace's .bazelrc doesn't define :ci) are now diagnosable at a glance.

Test plan

  • Eight unit tests in crates/bazelrc/src/lib.rs cover the rendered output: a golden-text assertion of the full CLI-source block (including the inline --announce-rc dump and ./ workspace-relative paths), rc-file source attribution via the Unresolved --config=X reference in: block, transitive expansion source attribution, the (none) rendering under --ignore_all_rc_files, a regression guard against internal jargon (injection, BazelTrait, extra_flags), ANSI escape embedding under with_ansi_errors(true), loaded_rc_files() filtering out the synthetic CLI source, and announce() rendering in-tree vs out-of-tree paths.
  • Four unit tests in crates/axl-runtime/src/term.rs cover the color-detection helper: NO_COLOR non-empty disables even on CI; NO_COLOR="" (empty) is treated as unset per the spec; no-CI-and-no-TTY means no color; each recognized CI env var triggers detection. Uses an RAII EnvGuard to snapshot/clear/restore process env around each case, serialized via a Mutex against cargo's parallel runner.
  • Manual: reproduced in a tempdir with a parent .aspect/config.axl setting --config=ci and a sub-workspace with MODULE.bazel but no .bazelrc. Confirmed only → 🎬 Running test task prints before the error, the bazelrc block renders in color on a TTY (and plain under NO_COLOR=1), and no AXL traceback wraps the message.

Follow-ups (separate PRs)

  • Auto-derive skip_config_if_missing from BazelTrait.extra_flags so framework-set configs become "soft" by design — the right primary fix for the sub-workspace case. This PR improves the error for cases where strict behavior remains correct.

@aspect-workflows

aspect-workflows Bot commented May 25, 2026

Copy link
Copy Markdown

✨ Aspect Workflows Tasks

📅 Mon May 25 22:38:13 UTC 2026

⚠️ 2 flagged tasks

  • ⚠️ delivery (delivery-gha) · ⏱ 26.5s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (2 warn · 1 skipped)
  • ⚠️ delivery (delivery-gha-debug) · ⏱ 41.6s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (2 warn · 1 skipped)

✅ 17 successful tasks

  • ✅ build (build-gha) · ⏱ 30.7s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (158 built)
  • ✅ build (build-gha-debug) · ⏱ 5m 34s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (158 built)
  • ✅ buildifier (buildifier-gha) · ⏱ 15.1s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ buildifier (buildifier-gha-debug) · ⏱ 28.6s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ buildifier (buildifier-gha-ephemeral) · ⏱ 45.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha) · ⏱ 11.8s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha-debug) · ⏱ 30.5s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha-ephemeral) · ⏱ 2m 40s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ gazelle (gazelle-from-source-gha) · ⏱ 12.5s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-from-source-gha-debug) · ⏱ 48.7s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-gha) · ⏱ 20.1s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-gha-debug) · ⏱ 19.7s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-gha-ephemeral) · ⏱ 41.9s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ lint (lint-gha) · ⏱ 21.9s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ lint (lint-gha-debug) · ⏱ 22.3s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ test (test-gha) · ⏱ 33s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)
  • ✅ test (test-gha-debug) · ⏱ 2m 49s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)

🔁 Reproduce

⚠️ delivery (delivery-gha · delivery-gha-debug)

aspect delivery --mode=always --track-state=false --dry-run=true

CI ran --mode=selective; --mode=always is the off-runner equivalent (selective change detection needs the Aspect Workflows delivery state backend).


⏱ Last updated Mon May 25 22:46:35 UTC 2026 · 📊 GitHub API quota 821/15,000 (5% used, resets in 24m)
🚀 Powered by Aspect CLI (v0.0.0-dev)  |  Aspect Build · X · LinkedIn · YouTube

@gregmagolan gregmagolan force-pushed the fix-undefined-config-error-message branch 9 times, most recently from a6593b0 to cc84d55 Compare May 25, 2026 07:10
@gregmagolan gregmagolan requested a review from thesayyn May 25, 2026 07:38
@gregmagolan gregmagolan force-pushed the fix-undefined-config-error-message branch from b8488e6 to a13ddd0 Compare May 25, 2026 11:37
// `lib/lifecycle.axl::announce`. Color setup mirrors the helper
// so the verdict glyph and labels match.
let color = std::io::stderr().is_terminal() || on_recognized_ci();
let color = crate::term::color_enabled();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its sort of sad that CI specific code is creeping into the rust code. ideally, this should be knob on the parse_bazelrc call.

@gregmagolan gregmagolan force-pushed the fix-undefined-config-error-message branch from a13ddd0 to f10670e Compare May 25, 2026 22:32
@gregmagolan gregmagolan marked this pull request as draft May 29, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants