{"record":{"id":"d6a356dcbc61bcd4","repo":"karpathy/nanochat","slug":"no-training-horizon-specified","errorCode":null,"errorMessage":"No training horizon specified","messagePattern":"No training horizon specified","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/base_train.py","lineNumber":353,"sourceCode":"# -----------------------------------------------------------------------------\n# Calculate the number of iterations we will train for and set up the various schedulers\n\n# num_iterations: either it is given, or from target flops, or from target data:param ratio (in that order)\nassert args.num_iterations > 0 or args.target_param_data_ratio > 0 or args.target_flops > 0\nif args.num_iterations > 0:\n    # Override num_iterations to a specific value if given\n    num_iterations = args.num_iterations\n    print0(f\"Using user-provided number of iterations: {num_iterations:,}\")\nelif args.target_flops > 0:\n    # Calculate the number of iterations from the target flops (used in scaling laws analysis, e.g. runs/scaling_laws.sh)\n    num_iterations = round(args.target_flops / (num_flops_per_token * total_batch_size))\n    print0(f\"Calculated number of iterations from target FLOPs: {num_iterations:,}\")\nelif args.target_param_data_ratio > 0:\n    # Calculate the number of iterations from the target param data ratio (the most common use case)\n    num_iterations = target_tokens // total_batch_size\n    print0(f\"Calculated number of iterations from target data:param ratio: {num_iterations:,}\")\nelse:\n    raise ValueError(\"No training horizon specified\")\ntotal_tokens = total_batch_size * num_iterations # the actual number of tokens we will train for\nprint0(f\"Total number of training tokens: {total_tokens:,}\")\nprint0(f\"Tokens : Scaling params ratio: {total_batch_size * num_iterations / num_scaling_params:.2f}\") # e.g. Chinchilla was ~20\nprint0(f\"Total training FLOPs estimate: {num_flops_per_token * total_tokens:e}\")\n\n# Learning rate schedule (linear warmup, constant, linear warmdown)\ndef get_lr_multiplier(it):\n    warmup_iters = args.warmup_steps\n    warmdown_iters = round(args.warmdown_ratio * num_iterations)\n    if it < warmup_iters:\n        return (it + 1) / warmup_iters\n    elif it <= num_iterations - warmdown_iters:\n        return 1.0\n    else:\n        progress = (num_iterations - it) / warmdown_iters\n        return progress * 1.0 + (1 - progress) * args.final_lr_frac\n\n# Momentum scheduler for Muon optimizer (warms up to 0.97, warms down to 0.90 during LR warmdown)","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/karpathy/nanochat/blob/92d63d4e8bb4df75c3b71618f31ddde2378b2bcd/scripts/base_train.py#L335-L371","documentation":"scripts/base_train.py computes the training length (num_iterations) from CLI args in priority order: --num-iterations, then --target-flops, then --target-param-data-ratio. If all three are 0/unset, there is no way to size the run, so it raises ValueError('No training horizon specified'). Note line 339 already asserts at least one is positive, so in practice you would hit the assert first; the ValueError is the same guard restated.","triggerScenarios":"Running base_train.py without any of --num-iterations, --target-flops, or --target-param-data-ratio (all default to 0), or explicitly passing 0/negative values for all three.","commonSituations":"A new launch command copied without the horizon flags; a runs/*.sh script edited and the ratio flag accidentally removed; overriding flags to 0 expecting a default horizon (there is none).","solutions":["Pass --target-param-data-ratio (typical Chinchilla-style choice, e.g. 20) for standard runs.","Or pass --num-iterations N for an exact step count.","Or pass --target-flops F for scaling-law runs.","Check your run script still contains one of these three flags after edits."],"exampleFix":"# before\ntorchrun --nproc_per_node=8 -m scripts.base_train\n\n# after\ntorchrun --nproc_per_node=8 -m scripts.base_train --target-param-data-ratio 20","handlingStrategy":"validation","validationCode":"assert args.num_iterations > 0 or args.target_flops > 0 or args.target_param_data_ratio > 0, (\n    \"specify one of --num-iterations, --target-flops, --target-param-data-ratio\"\n)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass one of the three horizon flags in launch scripts; Chinchilla-style --target-param-data-ratio 20 is the default choice.","Template run scripts with the horizon flag on its own commented line so edits don't drop it.","Fail fast in wrapper scripts by checking argv before torchrun launches."],"tags":["nanochat","training","cli","configuration","base-train"],"backgroundTag":null,"analyzedSha":"92d63d4e8bb4df75c3b71618f31ddde2378b2bcd","analyzedAt":"2026-08-15T03:11:54.371Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}