{"record":{"id":"cf162b439b3bd585","repo":"nodejs/node","slug":"s-only-allows-traceconfig-and-leaftraceconfig-as","errorCode":null,"errorMessage":"%s only allows TraceConfig and LeafTraceConfig as child configs.","messagePattern":"(.+?) only allows TraceConfig and LeafTraceConfig as child configs\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/run_perf.py","lineNumber":558,"sourceCode":"      # Produce total metric only when all traces have produced results.\n      if len(self.children) != len(results_for_total):\n        result_tracker.AddError(\n            'Not all traces have produced results. Can not compute total for '\n            '%s.' % self.name)\n        return\n\n      # Calculate total as a the geometric mean for results from all traces.\n      total_trace = LeafTraceConfig(\n          {\n              'name': 'Total',\n              'units': self.children[0].units\n          }, self, self.arch)\n      result_tracker.AddTraceResult(total_trace,\n                                    GeometricMean(results_for_total), '')\n\n  def AppendChild(self, node):\n    if node.__class__ not in (TraceConfig, LeafTraceConfig):\n      raise Exception(\n          \"%s only allows TraceConfig and LeafTraceConfig as child configs.\" %\n          type(self).__name__)\n    super(TraceConfig, self).AppendChild(node)\n\n\nclass RunnableConfig(TraceConfig):\n  \"\"\"Represents a runnable suite definition (i.e. has a main file).\n  \"\"\"\n  def __init__(self, suite, parent, arch):\n    super(RunnableConfig, self).__init__(suite, parent, arch)\n    self.arch = arch\n    assert self.main, \"No main js file provided\"\n    if not self.owners:\n      logging.error(\"No owners provided for %s\" % self.name)\n\n  def ChangeCWD(self, suite_path):\n    \"\"\"Changes the cwd to to path defined in the current graph.\n","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/run_perf.py#L540-L576","documentation":"Thrown by TraceConfig.AppendChild in V8's run_perf.py performance-test harness when a node is attached to a TraceConfig whose class is neither TraceConfig nor LeafTraceConfig. The performance suite is a tree (GraphConfig -> TraceConfig -> LeafTraceConfig), and TraceConfig deliberately restricts its children to those two types so the tree's shape stays valid for result aggregation (the geometric-mean 'Total' trace in ResultsTracker assumes LeafTraceConfig leaves).","triggerScenarios":"Calling node.AppendChild(someNode) where someNode.__class__ is not exactly TraceConfig or LeafTraceConfig (e.g. a GraphConfig, VariantConfig, or RunnableConfig attached to a TraceConfig parent). This is normally driven by BuildGraphConfigs misclassifying a suite dict, e.g. a suite entry that has both 'main' and 'tests' but whose resolved class is RunnableConfig being appended under a TraceConfig.","commonSituations":"See trigger scenarios.","solutions":["Inspect the suite JSON: every child under a trace-producing node must resolve to TraceConfig or LeafTraceConfig, not GraphConfig/RunnableConfig.","Check MakeGraphConfig selection rules (the 'main'/'tests' branching around run_perf.py:640) to see which class your child suite resolves to and adjust the keys so it maps to TraceConfig/LeafTraceConfig.","If you authored a new config subclass, either register it in the allowed tuple in AppendChild or attach it under GraphConfig (which accepts arbitrary children) instead of TraceConfig."],"exampleFix":"// before (suite JSON forces RunnableConfig under a TraceConfig)\n{ \"name\":\"x\", \"main\":\"x.js\", \"tests\":[ {\"name\":\"sub\"} ] }\n// after (drop 'main' so children resolve to TraceConfig/LeafTraceConfig, or move the block under a GraphConfig parent)\n{ \"name\":\"x\", \"tests\":[ {\"name\":\"sub\"} ] }","handlingStrategy":"validation","validationCode":"from tools.run_perf import TraceConfig, LeafTraceConfig\ndef safe_append(parent, child):\n    assert isinstance(parent, TraceConfig), 'parent must be TraceConfig'\n    if child.__class__ not in (TraceConfig, LeafTraceConfig):\n        raise ValueError(f'Refusing to append {child.__class__.__name__}; rebuild suite so child resolves to TraceConfig/LeafTraceConfig')\n    parent.AppendChild(child)","typeGuard":"def is_valid_trace_child(node) -> bool:\n    return node.__class__ in (TraceConfig, LeafTraceConfig)","tryCatchPattern":"null","preventionTips":["Always build the perf tree via BuildGraphConfigs rather than constructing nodes by hand.","Validate suite JSON against the expected schema before invoking run_perf.","When adding a new config class, decide upfront whether it belongs under GraphConfig (arbitrary children) or TraceConfig (restricted)."],"tags":["v8","perf-test","configuration","tree-structure"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}