nodejs/node · error · MBErr
Phase %s doesn't exist for %s on %s
Error message
Phase %s doesn't exist for %s on %s
What it means
Thrown by V8/Chromium's MB (meta-build) wrapper when a builder's entry in the mb config is a phased dict (e.g. {"x86": "...", "x64": "..."}) and the value passed via --phase is not one of its keys. MB coerces the phase to str() before the lookup, so the comparison is against the dict's string keys.
Source
Thrown at deps/v8/tools/mb/mb.py:626
if not self.args.builder_group in self.builder_groups:
raise MBErr('Builder groups name "%s" not found in "%s"' %
(self.args.builder_group, self.args.config_file))
config = _v8_builder_fallback(
self.args.builder, self.builder_groups[self.args.builder_group])
if not config:
raise MBErr(
'Builder name "%s" not found under builder_groups[%s] in "%s"' %
(self.args.builder, self.args.builder_group, self.args.config_file))
if isinstance(config, dict):
if self.args.phase is None:
raise MBErr('Must specify a build --phase for %s on %s' %
(self.args.builder, self.args.builder_group))
phase = str(self.args.phase)
if phase not in config:
raise MBErr('Phase %s doesn\'t exist for %s on %s' %
(phase, self.args.builder, self.args.builder_group))
return config[phase]
if self.args.phase is not None:
raise MBErr('Must not specify a build --phase for %s on %s' %
(self.args.builder, self.args.builder_group))
return config
def FlattenConfig(self, config):
mixins = self.configs[config]
vals = self.DefaultVals()
visited = []
self.FlattenMixins(mixins, vals, visited)
return vals
def DefaultVals(self):
return {View on GitHub (pinned to 1b2de5e052)
Solutions
- Open the mb config file (path referenced by --config-file) and list the valid phase keys for that builder.
- Re-run MB with one of those literal phase keys via --phase.
- If the builder shouldn't be phased, change its config entry from a dict to a flat string.
Example fix
// before v8/tools/mb/mb.py gen -m client.v8 -b 'V8 Linux - builder' --phase x86 // after (phase 'x86' not in dict; use a real key) v8/tools/mb/mb.py gen -m client.v8 -b 'V8 Linux - builder' --phase x64
Defensive patterns
Strategy: validation
Validate before calling
# Before invoking MB, confirm the phase is valid for the resolved config.
config = resolve_builder_config(builder_group, builder) # from the mb config file
if isinstance(config, dict):
assert str(phase) in config, (
f"phase {phase!r} not in {sorted(config.keys())}")
else:
assert phase is None, "non-phased builder; do not pass --phase" Prevention
- Have bot recipes enumerate valid phases from the config rather than hardcoding them.
- Document valid phase keys in builder config comments.
- Add a presubmit/lint that checks phased-builder recipes pass a known phase.
When it happens
Trigger: Running `mb.py <subcmd> -m <builder_group> -b <builder> --phase <X>` where builder_groups[group][builder] resolves to a dict and <X> is not a key of that dict.
Common situations: CI recipe passes a stale/renamed phase identifier; a new phased builder was added but the bot wasn't updated; integer-vs-string confusion because the phase is stringified before lookup.
Related errors
- Must not specify a build --phase for %s on %s
- args_file specified multiple times in mixins for %s on %s
- Unknown mixin "%s"
- Cannot generate isolate for %s since it is an additional_com
- MB is expecting GN_ARGS to be in the environment
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/37e965d0737fae7a.
Report an issue: GitHub.