nodejs/node · error · Exception

config_path must be a JSON file containing a dictionary

Error message

config_path must be a JSON file containing a dictionary

What it means

Thrown by analyzer Config.Init after the config file is parsed as valid JSON but the resulting top-level value is not a Python dict. The analyzer protocol requires the config to be a JSON object with keys like 'files', 'test_targets', and 'additional_compile_targets'. A JSON array, string, number, or bare value at the root is rejected.

Source

Thrown at tools/gyp/pylib/gyp/generator/analyzer.py:281

        self.test_target_names = set()

    def Init(self, params):
        """Initializes Config. This is a separate method as it raises an exception
        if there is a parse error."""
        generator_flags = params.get("generator_flags", {})
        config_path = generator_flags.get("config_path", None)
        if not config_path:
            return
        try:
            f = open(config_path)
            config = json.load(f)
            f.close()
        except OSError:
            raise Exception("Unable to open file " + config_path)
        except ValueError as e:
            raise Exception("Unable to parse config file " + config_path + str(e))
        if not isinstance(config, dict):
            raise Exception("config_path must be a JSON file containing a dictionary")
        self.files = config.get("files", [])
        self.additional_compile_target_names = set(
            config.get("additional_compile_targets", [])
        )
        self.test_target_names = set(config.get("test_targets", []))


def _WasBuildFileModified(build_file, data, files, toplevel_dir):
    """Returns true if the build file |build_file| is either in |files| or
    one of the files included by |build_file| is in |files|. |toplevel_dir| is
    the root of the source tree."""
    if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files:
        if debug:
            print("gyp file modified", build_file)
        return True

    # First element of included_files is the file itself.
    if len(data[build_file]["included_files"]) <= 1:

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Wrap the top-level value in a JSON object with the required keys, e.g. {"files": [...], "test_targets": [...], "additional_compile_targets": [...]}.
  2. Confirm the file's outermost characters are `{` and `}`, not `[` or a bare literal.
  3. Re-read the analyzer config schema and model your config on a known-good example.

Example fix

// before (config.json)
["src/a.cc", "src/b.cc"]
// after
{
  "files": ["src/a.cc", "src/b.cc"],
  "test_targets": [],
  "additional_compile_targets": []
}
Defensive patterns

Strategy: validation

Validate before calling

import json
with open('config.json') as f:
    cfg = json.load(f)
assert isinstance(cfg, dict), 'config root must be a JSON object'

Type guard

def is_config_object(cfg) -> bool:
    return isinstance(cfg, dict)

Try / catch

try:
    config.Init(params)
except Exception as e:
    if 'must be a JSON file containing a dictionary' in str(e):
        rewrite_config_as_object(config_path)
    raise

Prevention

When it happens

Trigger: The config_path file contains a valid JSON value that is not an object — e.g. `["a.cc"]` (array), `"a.cc"` (string), or a number. json.load() succeeds, but `isinstance(config, dict)` is False at analyzer.py:282.

Common situations: Writing a bare list of files instead of wrapping it in an object; misunderstanding the analyzer config schema; generating the config with a script that dumps a list rather than a dict.

Related errors


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