{"record":{"id":"a2d2395bcb9efc7a","repo":"kovidgoyal/kitty","slug":"spec-specified-more-than-two-easing-functions","errorCode":null,"errorMessage":"{spec} specified more than two easing functions","messagePattern":"(.+?) specified more than two easing functions","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"kitty/options/utils.py","lineNumber":1739,"sourceCode":"                n = max(2, n)\n            else:\n                n = max(1, n)\n        else:\n            n = max(1, int(parts[0]))\n        return cls(type='steps', jump_type=jump_type, num_steps=n)\n\n\ndef parse_animation(spec: str, interval: float = -1.0) -> tuple[float, EasingFunction, EasingFunction]:\n    with suppress(Exception):\n        interval = float(spec)\n        return interval, EasingFunction(), EasingFunction()\n\n    m = [EasingFunction(), EasingFunction()]\n\n    def parse_func(func_name: str, params: str) -> None:\n        idx = 1 if m[0] else 0\n        if m[idx]:\n            raise ValueError(f'{spec} specified more than two easing functions')\n        if func_name == 'cubic-bezier':\n            m[idx] = EasingFunction.cubic_bezier(params)\n        elif func_name == 'linear':\n            m[idx] = EasingFunction.linear(params)\n        elif func_name == 'steps':\n            m[idx] = EasingFunction.steps(params)\n        else:\n            raise KeyError(f'{func_name} is not a valid easing function')\n\n    for match in re.finditer(r'([-+.0-9a-zA-Z]+)(?:\\(([^)]*)\\)){0,1}', spec):\n        func_name, params = match.group(1, 2)\n        if params:\n            parse_func(func_name, params)\n            continue\n        with suppress(Exception):\n            interval = float(func_name)\n            continue\n        if func_name == 'ease-in-out':","sourceCodeStart":1721,"sourceCodeEnd":1757,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/options/utils.py#L1721-L1757","documentation":"kitty animation specs allow at most two easing functions (one for each half of the animation). parse_func tracks slots m[0]/m[1]; a third easing function raises this ValueError.","triggerScenarios":"A spec like '0.5:ease-in ease-out linear(...)' containing three easing function names, or repeated named easings.","commonSituations":"Chaining multiple easings expecting them to compose, or leftover text parsed as an easing name.","solutions":["Reduce to at most two easing functions in the spec","Keep the form interval:ease1 (optionally ease2 for the second half)"],"exampleFix":"# before\ncursor_blink_interval 0.5:ease-in ease-out ease-in-out\n# after\ncursor_blink_interval 0.5:ease-in ease-out","handlingStrategy":"validation","validationCode":"import re\ndef max_two_easings(spec: str) -> bool:\n    return len(re.findall(r'[-+.0-9a-zA-Z]+\\([^)]*\\)', spec)) <= 2 and len([t for t in re.findall(r'[-+.0-9a-zA-Z]+', spec) if t.isalpha()]) <= 2","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Limit specs to interval:ease1 [ease2]"],"tags":["kitty","config","animation","easing"],"backgroundTag":"too-many-values","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}