nodejs/node · error · Exception

{} not supported (target {}).

Error message

{} not supported (target {}).

What it means

msvs_emulation.MsvsSettings checks a set of MSVS-only fields (the 'unsupported_fields' list, which includes 'msvs_postbuild') against each configuration. When using a non-MSVS generator (typically ninja), these fields have no meaning, so each occurrence is reported as unsupported and the accumulated list is raised as a single Exception.

Source

Thrown at tools/gyp/pylib/gyp/msvs_emulation.py:240

                getattr(self, field)[configname] = config.get(field, default())

        self.msvs_cygwin_dirs = spec.get("msvs_cygwin_dirs", ["."])

        unsupported_fields = [
            "msvs_prebuild",
            "msvs_postbuild",
        ]
        unsupported = []
        for field in unsupported_fields:
            for config in configs.values():
                if field in config:
                    unsupported += [
                        "{} not supported (target {}).".format(
                            field, spec["target_name"]
                        )
                    ]
        if unsupported:
            raise Exception("\n".join(unsupported))

    def GetExtension(self):
        """Returns the extension for the target, with no leading dot.

        Uses 'product_extension' if specified, otherwise uses MSVS defaults based on
        the target type.
        """
        ext = self.spec.get("product_extension", None)
        return ext or gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec["type"], "")

    def GetVSMacroEnv(self, base_to_build=None, config=None):
        """Get a dict of variables mapping internal VS macro names to their gyp
        equivalents."""
        target_arch = self.GetArch(config)
        target_platform = "Win32" if target_arch == "x86" else target_arch
        target_name = self.spec.get("product_prefix", "") + self.spec.get(
            "product_name", self.spec["target_name"]
        )

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Remove the offending MSVS-only field(s) from the configuration(s) of that target.
  2. If you need the equivalent behavior under ninja, express it via generator-agnostic keys (e.g. postbuild steps via 'actions' or linker flags).
  3. Re-run gyp with the ninja generator.

Example fix

// before
'configurations': {
  'Release': { 'msvs_postbuild': 'echo done' }
}
// after
'configurations': {
  'Release': { }
}
// and, if needed, add a generator-agnostic action or linker flag
Defensive patterns

Strategy: validation

Validate before calling

UNSUPPORTED = {'msvs_postbuild'}  # extend to match unsupported_fields
for cfg_name, cfg in target_dict.get('configurations', {}).items():
    bad = UNSUPPORTED & set(cfg)
    if bad and using_ninja:
        raise ValueError(f'{target_dict["target_name"]}: {bad} unsupported under ninja')

Type guard

def no_unsupported_msvs_fields(target_dict: dict, generator: str) -> bool:
    if generator == 'ninja':
        bad = {'msvs_postbuild'}
        return all(not (bad & set(cfg)) for cfg in target_dict.get('configurations', {}).values())
    return True

Prevention

When it happens

Trigger: A target spec contains one of the unsupported_fields keys (e.g. msvs_postbuild) inside one of its configurations, and the build uses the ninja (or other non-msvs) generator that routes through msvs_emulation.

Common situations: Copying MSVS-specific settings from a Visual Studio build into a target that is now built with ninja; leftover msvs_postbuild from a porting effort.

Related errors


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