nodejs/node · error · Exception

Invalid suite configuration.

Error message

Invalid suite configuration.%s

What it means

Thrown by MakeGraphConfig in run_perf.py when a suite dict contains neither a 'main' key nor a 'tests' key, so the builder cannot decide whether the node is runnable, a graph, or a leaf. It is marked '# pragma: no cover' because the surrounding branches are expected to catch all valid combinations, so hitting it means the suite dict is structurally malformed.

Solutions

  1. Open the suite JSON named on the command line and find the node with neither 'main' nor 'tests'; add the missing key.
  2. If the node is meant to be a pure grouping node, give it a 'tests' array; if it should run a script, add 'main'.
  3. Re-run with the same JSON and confirm MakeGraphConfig now returns a concrete class (RunnableConfig / GraphConfig / LeafTraceConfig).

Example fix

// before
{ "name":"group" }
// after
{ "name":"group", "tests": [] }
Defensive patterns

Strategy: validation

Validate before calling

def validate_suite(suite):
    if 'main' not in suite and 'tests' not in suite:
        raise ValueError(f"Suite {suite.get('name','?')} has neither 'main' nor 'tests'; add one before running run_perf.")
    return True

Type guard

def is_valid_suite_dict(suite: dict) -> bool:
    return isinstance(suite, dict) and ('main' in suite or 'tests' in suite)

Try / catch

null

Prevention

When it happens

Trigger: A suite configuration entry missing both 'main' and 'tests' keys reaches MakeGraphConfig. This is only reachable if an upstream guard (which normally rejects keyless suites) is bypassed or if a suite file is hand-edited to drop both fields.

Common situations: Hand-editing a V8 perf benchmark JSON and deleting the 'tests' array from a node that had no 'main'; or a YAML->JSON conversion / templating step that stripped empty keys.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/e7b309c4d154b604. Report an issue: GitHub.

Appendix: source

Thrown at deps/v8/tools/run_perf.py:656

def GetGraphConfigClass(suite, parent):
  """Factory method for making graph configuration objects."""
  if isinstance(parent, TraceConfig):
    if suite.get("tests"):
      return TraceConfig
    return LeafTraceConfig
  elif suite.get('main') is not None:
    # A main file makes this graph runnable. Empty strings are accepted.
    if suite.get('tests'):
      # This graph has subgraphs (traces).
      return RunnableConfig
    else:
      # This graph has no subgraphs, it's a leaf.
      return RunnableLeafTraceConfig
  elif suite.get('tests'):
    # This is neither a leaf nor a runnable.
    return GraphConfig
  else:  # pragma: no cover
    raise Exception('Invalid suite configuration.' + str(suite)[:200])


def BuildGraphConfigs(suite, parent, arch):
  """Builds a tree structure of graph objects that corresponds to the suite
  configuration.

  - GraphConfig:
    - Can have arbitrary children
    - can be used to store properties used by its children

  - VariantConfig
    - Has variants of the same (any) type as children

  For all other configs see the override AppendChild methods.

  Example 1:
  - GraphConfig
    - RunnableLeafTraceConfig (no children)

View on GitHub (pinned to 1b2de5e052)