{"record":{"id":"d2db27cdf3f2e75e","repo":"karpathy/nanoGPT","slug":"unknown-config-key-key","errorCode":null,"errorMessage":"Unknown config key: {key}","messagePattern":"Unknown config key: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"configurator.py","lineNumber":47,"sourceCode":"    else:\n        # assume it's a --key=value argument\n        assert arg.startswith('--')\n        key, val = arg.split('=')\n        key = key[2:]\n        if key in globals():\n            try:\n                # attempt to eval it it (e.g. if bool, number, or etc)\n                attempt = literal_eval(val)\n            except (SyntaxError, ValueError):\n                # if that goes wrong, just use the string\n                attempt = val\n            # ensure the types match ok\n            assert type(attempt) == type(globals()[key])\n            # cross fingers\n            print(f\"Overriding: {key} = {attempt}\")\n            globals()[key] = attempt\n        else:\n            raise ValueError(f\"Unknown config key: {key}\")\n","sourceCodeStart":29,"sourceCodeEnd":48,"githubUrl":"https://github.com/karpathy/nanoGPT/blob/3adf61e154c3fe3fca428ad6bc3818b27a3b8291/configurator.py#L29-L48","documentation":"This error comes from nanoGPT's 'Poor Man's Configurator' (configurator.py), which is exec'd at the top of train.py/sample.py and mutates the script's globals(). For every --key=value command-line argument, it checks whether key already exists in globals(); if not, there is no config variable to override, so it raises ValueError('Unknown config key: ...'). In short: you passed a --flag whose name does not match any variable defined in the exec'd script or in any config file that ran before it.","triggerScenarios":"Running e.g. `python train.py config/train_shakespeare_char.py --dtype=bfloat16` when the exec'd script (train.py plus the config file) never defines a global named `dtype`. Also triggered by typos (`--batch_size` vs `--batch-size`, which instead parses as key `batch-size`), by flags that only exist in a different config file (e.g. using a GPT-2 fine-tune flag against a base train script), or by arguments intended for another program (e.g. a launcher like torchrun) placed after the script's config args and containing '='.","commonSituations":"Copy-pasting a training command from a different nanoGPT version or model recipe whose variable names changed; assuming every variable in a config file is overridable when train.py only overridable if it also declares it in its own top-level code; passing WandB/SLURM/torchrun flags with an '=' to a script that exec's configurator.py; typos or case mismatches in flag names; forgetting to pass the base config file first (e.g. `python train.py --batch_size=32` with no config file, so almost nothing is in globals()).","solutions":["Check the exact variable name: open the config file you passed (or train.py's top-level assignments) and confirm the global exists, e.g. it must be `--batch_size=32` matching `batch_size = 64`.","Make sure you passed the base config file before the override, e.g. `python train.py config/train_shakespeare_char.py --batch_size=32` — without the config file the key may never be defined.","Fix typos, casing, and dashes: the parser splits on '=' and strips a leading '--', so `--batch-size=32` yields key `batch-size`, which will never match `batch_size`.","If you genuinely need a new knob, define it in the config file (or at the top of train.py) with a default value first, then override it on the command line.","Keep flags belonging to launchers (torchrun, accelerate, WandB env-style args) out of the positional/override section that configurator.py scans; set them as environment variables instead."],"exampleFix":"# before (train.py never defines a global named `dtype`)\n$ python train.py config/train_shakespeare_char.py --dtype=bfloat16\nValueError: Unknown config key: dtype\n\n# after (dtype is a global that train.py/config defines)\n$ python train.py config/train_shakespeare_char.py --dtype=bf16\n# or add to the config file:\n#   dtype = 'bf16'\n# then run: python train.py config/train_shakespeare_char.py --dtype='bf16'","handlingStrategy":"validation","validationCode":"import sys\nfrom ast import literal_eval\n\n# run before launching the training script\nconfig_globals = set()\nfor a in sys.argv[1:]:\n    if a.endswith('.py') and '=' not in a:\n        src = open(a).read()\n        ns = {}\n        exec(compile(src, a, 'exec'), ns)\n        config_globals.update(k for k in ns if not k.startswith('_'))\n\nbad = [a for a in sys.argv[1:]\n       if a.startswith('--') and '=' in a and a[2:].split('=')[0] not in config_globals]\nassert not bad, f'Unknown config keys: {bad}'","typeGuard":"def is_known_config_key(key: str, known: set[str]) -> bool:\n    \"\"\"True if `key` matches a global defined by the script or its config files.\"\"\"\n    return key in known\n\n# usage:\n# key = '--batch_size=32'[2:].split('=')[0]\n# if not is_known_config_key(key, known_globals): sys.exit(f'unknown key {key}')","tryCatchPattern":"# only if you exec configurator.py yourself / wrap script startup\ntry:\n    exec(open('configurator.py').read())\nexcept ValueError as e:\n    if str(e).startswith('Unknown config key:'):\n        key = str(e).split(':')[-1].strip()\n        sys.exit(f'config error: {key!r} is not defined in the script or config file; add it to the config or fix the flag name')\n    raise","preventionTips":["Read the config file you are overriding and copy variable names verbatim (snake_case, no dashes).","Always pass the base config file before any --key=value overrides.","Prefer editing a small custom config file over long CLI override strings; fewer flags means fewer typo opportunities.","Dry-run new commands with `--help`-style inspection first, or list config file contents (the configurator prints them) to see valid keys.","Keep launcher/framework flags (torchrun, accelerate, WandB) as environment variables, never inline after the script name."],"tags":["python","configuration","cli","nanogpt","command-line-args"],"backgroundTag":null,"analyzedSha":"3adf61e154c3fe3fca428ad6bc3818b27a3b8291","analyzedAt":"2026-08-15T00:45:35.790Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}