{"record":{"id":"be67de4130c1ed0b","repo":"huggingface/pytorch-image-models","slug":"api-has-changed-state-steps-argument-must-conta","errorCode":null,"errorMessage":"API has changed, `state_steps` argument must contain a list of singleton tensors","messagePattern":"API has changed, `state_steps` argument must contain a list of singleton tensors","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"timm/optim/adamw.py","lineNumber":205,"sourceCode":"        foreach: Optional[bool] = None,\n        capturable: bool = False,\n        *,\n        amsgrad: bool,\n        beta1: float,\n        beta2: float,\n        lr: float,\n        weight_decay: float,\n        eps: float,\n        caution: bool,\n        maximize: bool,\n        max_lr: Optional[float],\n) -> None:\n    r\"\"\"Functional API that performs AdamW algorithm computation.\n      See AdamWLegacy class for details.\n    \"\"\"\n\n    if not all(isinstance(t, torch.Tensor) for t in state_steps):\n        raise RuntimeError(\n            'API has changed, `state_steps` argument must contain a list of' +\n            ' singleton tensors')\n\n    if foreach is None:\n        try:\n            # cannot do foreach if this overload doesn't exist when caution enabled\n            foreach = not caution or 'Scalar' in torch.ops.aten._foreach_maximum_.overloads()\n            # Match native PyTorch: tensor lr without capturable mode is supported by the single-tensor path.\n            if foreach and torch.is_tensor(lr) and not capturable:\n                foreach = False\n        except Exception:\n            foreach = False\n\n    if foreach and not torch.jit.is_scripting():\n        func = _multi_tensor_adamw\n    else:\n        func = _single_tensor_adamw\n","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/huggingface/pytorch-image-models/blob/9a5261e31b3b5128526eb2658333b4c0a54464ae/timm/optim/adamw.py#L187-L223","documentation":"The functional timm.optim.adamw.adamw() API requires state_steps to be a list of singleton torch tensors (one per parameter), matching PyTorch's modern functional optimizer API. Passing floats or ints (the pre-1.5 API) triggers this guard.","triggerScenarios":"Calling timm.optim.adamw.adamw(..., state_steps=[0, 1, 2]) with Python numbers instead of state_steps=[torch.tensor(0.), ...]. It is also raised if any element of the list is not a torch.Tensor.","commonSituations":"Copying old tutorial code that used the pre-2020 functional Adam API, or hand-rolling a training loop that tracks step counts as ints and forwards them to the functional API.","solutions":["Convert each step count to a tensor: state_steps = [torch.tensor(float(step)) for step in state_steps]","Or let the AdamW class manage state and call step() instead of the functional API","If migrating from torch.optim.adamw, reuse the same tensor-based state_steps convention"],"exampleFix":"# before\nadamw(params, grads, exp_avgs, exp_avg_sqs, max_exp_avg_sqs, state_steps=[0], lr=1e-3)\n# after\nadamw(params, grads, exp_avgs, exp_avg_sqs, max_exp_avg_sqs, state_steps=[torch.tensor(0.)], lr=1e-3)","handlingStrategy":"validation","validationCode":"assert all(isinstance(t, torch.Tensor) and t.numel() == 1 for t in state_steps)","typeGuard":"def valid_state_steps(state_steps: list) -> bool:\n    return all(isinstance(t, torch.Tensor) and t.numel() == 1 for t in state_steps)","tryCatchPattern":null,"preventionTips":["Prefer the class API (AdamW.step()) over the functional API","Initialize state_steps as torch.zeros(1) tensors from the start","Convert legacy int counters once at migration time"],"tags":["optimizer","adamw","functional-api","pytorch-version"],"backgroundTag":"optimizer-functional-api-state-format","analyzedSha":"9a5261e31b3b5128526eb2658333b4c0a54464ae","analyzedAt":"2026-08-27T02:34:25.417Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}