{"record":{"id":"5a09f7e5ae18a4a1","repo":"nodejs/node","slug":"failed-to-parse-config-file-s-s","errorCode":null,"errorMessage":"Failed to parse config file \"%s\": %s","messagePattern":"Failed to parse config file \"(.+?)\": (.+?)","errorType":"exception","errorClass":"MBErr","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/mb/mb.py","lineNumber":565,"sourceCode":"                         self.args.builder_group, self.args.builder + '.json')\n    if not self.Exists(path):\n      return {}\n\n    contents = json.loads(self.ReadFile(path))\n    gn_args = ' '.join(contents.get('gn_args', []))\n\n    vals = self.DefaultVals()\n    vals['gn_args'] = gn_args\n    return vals\n\n  def ReadConfigFile(self):\n    if not self.Exists(self.args.config_file):\n      raise MBErr('config file not found at %s' % self.args.config_file)\n\n    try:\n      contents = ast.literal_eval(self.ReadFile(self.args.config_file))\n    except SyntaxError as e:\n      raise MBErr('Failed to parse config file \"%s\": %s' %\n                 (self.args.config_file, e)) from e\n\n    self.configs = contents['configs']\n    self.luci_tryservers = contents.get('luci_tryservers', {})\n    self.builder_groups = contents['builder_groups']\n    self.mixins = contents['mixins']\n\n  def ReadIsolateMap(self):\n    if not self.args.isolate_map_files:\n      self.args.isolate_map_files = [self.default_isolate_map]\n\n    for f in self.args.isolate_map_files:\n      if not self.Exists(f):\n        raise MBErr('isolate map file not found at %s' % f)\n    isolate_maps = {}\n    for isolate_map in self.args.isolate_map_files:\n      try:\n        isolate_map = ast.literal_eval(self.ReadFile(isolate_map))","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/mb/mb.py#L547-L583","documentation":"ReadConfigFile() parses mb_config.pyl with ast.literal_eval. If the file is not a valid Python literal (syntax error), the SyntaxError is caught and re-raised as MBErr('Failed to parse config file \"%s\": %s') chaining the original via `from e`. The message includes the file path and the underlying parse error detail.","triggerScenarios":"mb_config.pyl contains a Python syntax error: unbalanced brackets, a stray comma, an invalid token, a dangling quote, or trailing junk. ast.literal_eval raises SyntaxError, caught and converted to MBErr.","commonSituations":"Hand-editing mb_config.pyl and leaving a syntax error; a botched merge conflict resolution; copy-paste that broke quoting; a tab/space inconsistency in a Python literal.","solutions":["Open mb_config.pyl and run `python3 -c \"import ast; ast.literal_eval(open('infra/mb/mb_config.pyl').read())\"` to get the exact line/column of the syntax error, then fix it.","Re-resolve any merge-conflict markers (<<<<<<, =======, >>>>>>) left in the file.","Validate with `mb.py validate -f <file>` after the fix."],"exampleFix":"// before\n  'configs': {\n    'x64.release': {'mixins': ['x64', 'release']}   // missing trailing comma before next entry\n  }\n// after\n  'configs': {\n    'x64.release': {'mixins': ['x64', 'release']},\n  }","handlingStrategy":"validation","validationCode":"import ast\ntry:\n    ast.literal_eval(open(mb_config_path).read())\nexcept SyntaxError as e:\n    sys.exit(f'mb_config.pyl parse error at line {e.lineno}: {e.msg}')","typeGuard":"null","tryCatchPattern":"try:\n    ast.literal_eval(text)\nexcept SyntaxError as e:\n    raise MBErr(f'Failed to parse config file \"{path}\": {e}') from e","preventionTips":["After editing mb_config.pyl, run `python3 -c \"import ast; ast.literal_eval(open('infra/mb/mb_config.pyl').read())\"` to catch syntax errors.","Always fully resolve merge-conflict markers in config files.","Use `mb.py validate` as a pre-commit hook for mb_config.pyl."],"tags":["mb","config","parse-error","ast","v8-build"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}