{"record":{"id":"e8296e8d8e25c9c7","repo":"AUTOMATIC1111/stable-diffusion-webui","slug":"invalid-learning-rate-schedule-it-should-be-a-num","errorCode":null,"errorMessage":"Invalid learning rate schedule. It should be a number or, for example, like \"0.001:100, 0.00001:1000, 1e-5:10000\" to have lr of 0.001 until step 100, 0.00001 until 1000, and 1e-5 until 10000.","messagePattern":"Invalid learning rate schedule\\. It should be a number or, for example, like \"0\\.001:100, 0\\.00001:1000, 1e-5:10000\" to have lr of 0\\.001 until step 100, 0\\.00001 until 1000, and 1e-5 until 10000\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"modules/textual_inversion/learn_schedule.py","lineNumber":36,"sourceCode":"                tmp = pair.split(':')\r\n                if len(tmp) == 2:\r\n                    step = int(tmp[1])\r\n                    if step > cur_step:\r\n                        self.rates.append((float(tmp[0]), min(step, max_steps)))\r\n                        self.maxit += 1\r\n                        if step > max_steps:\r\n                            return\r\n                    elif step == -1:\r\n                        self.rates.append((float(tmp[0]), max_steps))\r\n                        self.maxit += 1\r\n                        return\r\n                else:\r\n                    self.rates.append((float(tmp[0]), max_steps))\r\n                    self.maxit += 1\r\n                    return\r\n            assert self.rates\r\n        except (ValueError, AssertionError) as e:\r\n            raise Exception('Invalid learning rate schedule. It should be a number or, for example, like \"0.001:100, 0.00001:1000, 1e-5:10000\" to have lr of 0.001 until step 100, 0.00001 until 1000, and 1e-5 until 10000.') from e\r\n\r\n\r\n    def __iter__(self):\r\n        return self\r\n\r\n    def __next__(self):\r\n        if self.it < self.maxit:\r\n            self.it += 1\r\n            return self.rates[self.it - 1]\r\n        else:\r\n            raise StopIteration\r\n\r\n\r\nclass LearnRateScheduler:\r\n    def __init__(self, learn_rate, max_steps, cur_step=0, verbose=True):\r\n        self.schedules = LearnScheduleIterator(learn_rate, max_steps, cur_step)\r\n        (self.learn_rate,  self.end_step) = next(self.schedules)\r\n        self.verbose = verbose\r","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/textual_inversion/learn_schedule.py#L18-L54","documentation":"LearnScheduleParser in textual_inversion training parses the learning-rate schedule string. Accepted forms are a single number ('0.001') or comma-separated 'rate:step' pairs ('0.001:100, 0.00001:1000'). Any token that float() cannot parse, or a schedule yielding no rates at all, raises ValueError/AssertionError which is re-raised with this explanatory message.","triggerScenarios":"Entering a schedule like '0.001:100,abc:200', 'lr:100', an empty string, or trailing commas in the textual-inversion/embedding trainer's Learning rate field; values with spaces inside a token such as '0.001 :100' can also fail float().","commonSituations":"Typos in the training tab; pasting a schedule from a tutorial that used a different format; localized keyboards inserting non-breaking spaces or comma decimal separators (0,001).","solutions":["Use a plain float (e.g. 0.001) if you do not need step-based decay","Format the schedule exactly as 'rate:steps, rate:steps' with dot decimals and ASCII colons/commas","Remove trailing/leading commas and verify each rate parses with float() before starting training"],"exampleFix":"# before\nschedule = '0.001:100, 0,00001:1000'\n# after\nschedule = '0.001:100, 0.00001:1000'","handlingStrategy":"validation","validationCode":"def parse_schedule_ok(schedule: str) -> bool:\n    schedule = schedule.strip()\n    if not schedule:\n        return False\n    try:\n        for token in schedule.split(','):\n            parts = [p.strip() for p in token.split(':')]\n            if len(parts) not in (1, 2):\n                return False\n            float(parts[0])\n            if len(parts) == 2:\n                int(parts[1])\n        return True\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the schedule string in UI glue code before starting training","Use dot decimal separators and ASCII ':' / ','","Default the field to a plain float for casual users"],"tags":["training","textual-inversion","validation","user-input"],"backgroundTag":null,"analyzedSha":"82a973c04367123ae98bd9abdf80d9eda9b910e2","analyzedAt":"2026-08-14T16:46:43.225Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}