nodejs/node · error · ValueError

Dictionary key is not a valid GN identifier.

Error message

Dictionary key is not a valid GN identifier.

What it means

ValueError raised by GenerateTokens when a dict key is a string but not a valid GN identifier: it must be non-empty, must not start with a digit, and must contain only alphanumerics and underscores (key.replace('_','').isalnum()). This guard fires after the isinstance(key, str) check.

Source

Thrown at tools/gypi_to_gn.py:151

      yield str(v)

    elif isinstance(v, list):
      yield '['
      for i, item in enumerate(v):
        if i > 0:
          yield ','
        for tok in GenerateTokens(item, level + 1):
          yield tok
      yield ']'

    elif isinstance(v, dict):
      if level > 0:
        yield '{'
      for key in sorted(v):
        if not isinstance(key, str):
          raise ValueError('Dictionary key is not a string.')
        if not key or key[0].isdigit() or not key.replace('_', '').isalnum():
          raise ValueError('Dictionary key is not a valid GN identifier.')
        yield key  # No quotations.
        yield '='
        for tok in GenerateTokens(v[key], level + 1):
          yield tok
      if level > 0:
        yield '}'

    else:  # Not supporting float: Add only when needed.
      raise ValueError('Unsupported type when printing to GN.')

  can_start = lambda tok: tok and tok not in ',}]='
  can_end = lambda tok: tok and tok not in ',{[='

  # Adds whitespaces, trying to keep everything (except dicts) in 1 line.
  def PlainGlue(gen):
    prev_tok = None
    for i, tok in enumerate(gen):
      if i > 0:

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Rename keys to use only alphanumerics and underscores before conversion.
  2. Add a preprocessing step that maps problematic keys to valid GN identifiers.
  3. Review GYP files for hyphenated/dotted keys that have no GN equivalent and refactor the build logic.

Example fix

# before (GYP key 'include-dirs' is rejected)

# after (rename to 'include_dirs' in GYP source / mapping)
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_gn_identifier(key: str) -> bool:
    return bool(key) and not key[0].isdigit() and key.replace('_', '').isalnum()

Type guard

def valid_gn_keys(d: dict) -> bool:
    return all(isinstance(k, str) and k and not k[0].isdigit()
               and k.replace('_', '').isalnum() for k in d)

Try / catch

try:
    list(GenerateTokens(data))
except ValueError as e:
    if 'valid GN identifier' in str(e):
        pass  # rename keys (dashes->underscores) and retry

Prevention

When it happens

Trigger: A key like '1foo' (leading digit), 'foo-bar' (dash not allowed), '' (empty), or 'foo.bar' (dot not allowed). GN identifiers are [A-Za-z_][A-Za-z0-9_]*.

Common situations: GYP keys containing dashes/dots (common in GYP 'variables' or 'conditions' with hyphenated names) being converted to GN, where such characters are illegal in identifiers.

Related errors


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