{"record":{"id":"37e965d0737fae7a","repo":"nodejs/node","slug":"phase-s-doesn-t-exist-for-s-on-s","errorCode":null,"errorMessage":"Phase %s doesn't exist for %s on %s","messagePattern":"Phase (.+?) doesn't exist for (.+?) on (.+?)","errorType":"exception","errorClass":"MBErr","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/mb/mb.py","lineNumber":626,"sourceCode":"    if not self.args.builder_group in self.builder_groups:\n      raise MBErr('Builder groups name \"%s\" not found in \"%s\"' %\n                  (self.args.builder_group, self.args.config_file))\n\n    config = _v8_builder_fallback(\n        self.args.builder, self.builder_groups[self.args.builder_group])\n\n    if not config:\n      raise MBErr(\n        'Builder name \"%s\"  not found under builder_groups[%s] in \"%s\"' %\n        (self.args.builder, self.args.builder_group, self.args.config_file))\n\n    if isinstance(config, dict):\n      if self.args.phase is None:\n        raise MBErr('Must specify a build --phase for %s on %s' %\n                    (self.args.builder, self.args.builder_group))\n      phase = str(self.args.phase)\n      if phase not in config:\n        raise MBErr('Phase %s doesn\\'t exist for %s on %s' %\n                    (phase, self.args.builder, self.args.builder_group))\n      return config[phase]\n\n    if self.args.phase is not None:\n      raise MBErr('Must not specify a build --phase for %s on %s' %\n                  (self.args.builder, self.args.builder_group))\n    return config\n\n  def FlattenConfig(self, config):\n    mixins = self.configs[config]\n    vals = self.DefaultVals()\n\n    visited = []\n    self.FlattenMixins(mixins, vals, visited)\n    return vals\n\n  def DefaultVals(self):\n    return {","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/mb/mb.py#L608-L644","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nv8/tools/mb/mb.py gen -m client.v8 -b 'V8 Linux - builder' --phase x86\n// after (phase 'x86' not in dict; use a real key)\nv8/tools/mb/mb.py gen -m client.v8 -b 'V8 Linux - builder' --phase x64","handlingStrategy":"validation","validationCode":"# Before invoking MB, confirm the phase is valid for the resolved config.\nconfig = resolve_builder_config(builder_group, builder)  # from the mb config file\nif isinstance(config, dict):\n    assert str(phase) in config, (\n        f\"phase {phase!r} not in {sorted(config.keys())}\")\nelse:\n    assert phase is None, \"non-phased builder; do not pass --phase\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["mb","build-config","v8","gn","chromium"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}