{"record":{"id":"da3855e0e22b21b3","repo":"nodejs/node","slug":"invalid-suite-configuration","errorCode":null,"errorMessage":"Invalid suite configuration.","messagePattern":"Invalid suite configuration\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/run_perf.py","lineNumber":741,"sourceCode":"      for subsuite in variant_suite.get('tests', []):\n        BuildGraphConfigs(subsuite, variant_graph, arch)\n  parent.AppendChild(graph)\n  return graph\n\n\ndef FlattenRunnables(node, node_cb):\n  \"\"\"Generator that traverses the tree structure and iterates over all\n  runnables.\n  \"\"\"\n  node_cb(node)\n  if isinstance(node, RunnableConfig):\n    yield node\n  elif isinstance(node, Node):\n    for child in node._children:\n      for result in FlattenRunnables(child, node_cb):\n        yield result\n  else:  # pragma: no cover\n    raise Exception('Invalid suite configuration.')\n\n\ndef find_build_directory(base_path, arch):\n  \"\"\"Returns the location of d8 or node in the build output directory.\n\n  This supports a seamless transition between legacy build location\n  (out/Release) and new build location (out/build).\n  \"\"\"\n  def is_build(path):\n    # We support d8 or node as executables. We don't support testing on\n    # Windows.\n    return (os.path.isfile(os.path.join(path, 'd8')) or\n            os.path.isfile(os.path.join(path, 'node')))\n  possible_paths = [\n    # Location developer wrapper scripts is using.\n    '%s.release' % arch,\n    # Current build location on bots.\n    'build',","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/run_perf.py#L723-L759","documentation":"Thrown by FlattenRunnables in run_perf.py during tree traversal when a node is neither a RunnableConfig nor an instance of the tree Node base class. Marked '# pragma: no cover' because the tree builder is expected to always produce Node subclasses, so reaching this means the tree was constructed outside the normal BuildGraphConfigs path or corrupted.","triggerScenarios":"FlattenRunnables is called over a structure that contains a non-Node object (e.g. a raw dict, None, or a primitive) because something injected a foreign value into a node's _children list, or the traversal root itself is not a Node.","commonSituations":"A custom perf-harness or monkey-patch that builds the runnable tree by hand instead of via BuildGraphConfigs; or a bug in AppendChild that allowed a non-Node into _children.","solutions":["Ensure the tree passed to FlattenRunnables is always built by BuildGraphConfigs (which only ever instantiates Node subclasses).","If you construct nodes manually, verify every element in each node._children is an instance of Node before traversal.","Add an assertion at the BuildGraphConfigs entry point that the root is a Node, to fail early with a clear message."],"exampleFix":"null","handlingStrategy":"type-guard","validationCode":"from tools.run_perf import Node\ndef assert_tree_is_valid(root):\n    stack = [root]\n    while stack:\n        n = stack.pop()\n        if not isinstance(n, Node):\n            raise TypeError(f'Non-Node object in tree: {n!r}')\n        stack.extend(getattr(n, '_children', []))","typeGuard":"from tools.run_perf import Node\ndef is_tree_of_nodes(root) -> bool:\n    stack = [root]\n    while stack:\n        n = stack.pop()\n        if not isinstance(n, Node):\n            return False\n        stack.extend(getattr(n, '_children', []))\n    return True","tryCatchPattern":"null","preventionTips":["Only ever build runnable trees with BuildGraphConfigs.","Never mutate node._children directly; use AppendChild which type-checks."],"tags":["v8","perf-test","tree-structure","unreachable"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}