{"record":{"id":"6ae057fff0ce809d","repo":"nodejs/node","slug":"args-file-specified-multiple-times-in-mixins-for","errorCode":null,"errorMessage":"args_file specified multiple times in mixins for %s on %s","messagePattern":"args_file specified multiple times in mixins for (.+?) on (.+?)","errorType":"exception","errorClass":"MBErr","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/mb/mb.py","lineNumber":663,"sourceCode":"      'args_file': '',\n      'cros_passthrough': False,\n      'gn_args': '',\n    }\n\n  def FlattenMixins(self, mixins, vals, visited):\n    for m in mixins:\n      if m not in self.mixins:\n        raise MBErr('Unknown mixin \"%s\"' % m)\n\n      visited.append(m)\n\n      mixin_vals = self.mixins[m]\n\n      if 'cros_passthrough' in mixin_vals:\n        vals['cros_passthrough'] = mixin_vals['cros_passthrough']\n      if 'args_file' in mixin_vals:\n        if vals['args_file']:\n          raise MBErr('args_file specified multiple times in mixins '\n                      'for %s on %s' %\n                      (self.args.builder, self.args.builder_group))\n        vals['args_file'] = mixin_vals['args_file']\n      if 'gn_args' in mixin_vals:\n        if vals['gn_args']:\n          vals['gn_args'] += ' ' + mixin_vals['gn_args']\n        else:\n          vals['gn_args'] = mixin_vals['gn_args']\n\n      if 'mixins' in mixin_vals:\n        self.FlattenMixins(mixin_vals['mixins'], vals, visited)\n    return vals\n\n  def RunGNGen(self, vals, compute_grit_inputs_for_analyze=False):\n    build_dir = self.args.path[0]\n\n    cmd = self.GNCmd('gen', build_dir, '--check')\n    gn_args = self.GNArgs(vals)","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/mb/mb.py#L645-L681","documentation":"FlattenMixins sets vals['args_file'] from the first mixin that provides one; encountering a second mixin (in the flattened transitive set) that also sets args_file is treated as an ambiguous, unresolvable config and aborts.","triggerScenarios":"A config whose transitive mixin closure contains two or more mixins each carrying an 'args_file' key (including via nested mixins).","commonSituations":"Composing reusable mixins where more than one happens to set args_file; refactor that duplicated args_file across multiple mixins; merge combining two pre-existing args_file mixins.","solutions":["Enumerate the config's transitive mixin set and locate every mixin carrying args_file.","Keep args_file on exactly one mixin (or remove it from all but one).","Factor the shared args_file into a single common mixin that the others depend on."],"exampleFix":"// before\n// mixin A: {'args_file': '//build/args/a.gn'}\n// mixin B: {'args_file': '//build/args/b.gn'}\n// config:  {'mixins': ['A', 'B']}\n// after\n// mixin A: {'args_file': '//build/args/a.gn'}\n// mixin B: {}  (drop args_file, or merge into A)","handlingStrategy":"validation","validationCode":"# Detect configs whose flattened mixin set has >1 args_file.\ndef flatten(mixin_name, seen):\n    m = mixins[mixin_name]\n    if 'args_file' in m:\n        seen.append((mixin_name, m['args_file']))\n    for sub in m.get('mixins', []):\n        flatten(sub, seen)\nfor cfg_name, entry in configs.items():\n    seen = []\n    for m in (entry if isinstance(entry, list) else entry.get('mixins', [])):\n        flatten(m, seen)\n    assert len(seen) <= 1, f\"{cfg_name} has multiple args_file: {seen}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep args_file on a single shared mixin.","Add a presubmit check that flags configs with duplicate args_file."],"tags":["mb","build-config","v8","gn","config-validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}