{"record":{"id":"364317737073cfc7","repo":"kovidgoyal/kitty","slug":"not-a-valid-unit-x-allowed-units-are-default","errorCode":null,"errorMessage":"Not a valid unit: {x}. Allowed units are: {default_unit}, {\", \".join(extra_units)}","messagePattern":"Not a valid unit: (.+?)\\. Allowed units are: (.+?), (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"kitty/conf/utils.py","lineNumber":81,"sourceCode":"\n\ndef unit_float(x: ConvertibleToNumbers) -> float:\n    return max(0, min(float(x), 1))\n\n\ndef signed_unit_float(x: ConvertibleToNumbers) -> float:\n    return max(-1, min(float(x), 1))\n\n\ndef number_with_unit(x: str, default_unit: str, *extra_units: str) -> tuple[float, str]:\n    if (mat := number_unit_pat.match(x)) is not None:\n        try:\n            value = float(mat.group(1))\n        except Exception as e:\n            raise ValueError(f'Not a number: {x} with error: {e}')\n        unit = mat.group(2) or default_unit\n        if unit != default_unit and unit not in extra_units:\n            raise ValueError(f'Not a valid unit: {x}. Allowed units are: {default_unit}, {\", \".join(extra_units)}')\n        return value, unit\n    raise ValueError(f'Invalid number with unit: {x}')\n\n\ndef to_bool(x: str) -> bool:\n    return x.lower() in ('y', 'yes', 'true')\n\n\nclass ToCmdline:\n    def __init__(self) -> None:\n        self.override_env: dict[str, str] | None = None\n\n    def __enter__(self) -> 'ToCmdline':\n        return self\n\n    def __exit__(self, *a: Any) -> None:\n        self.override_env = None\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/conf/utils.py#L63-L99","documentation":"number_with_unit raises ValueError when a value carries a unit that is neither the default unit nor one of the allowed extra units. E.g. a pixels-only option given 'em' or 'col'.","triggerScenarios":"Config string like '10em' for an option whose parser was created with default_unit='px' and no 'em' in extra_units.","commonSituations":"Copying option values between kitty options that accept different unit sets; assuming CSS units are universally allowed.","solutions":["Use the default unit (usually no suffix needed)","Check the option's allowed units in kitty docs","Remove the unit suffix entirely"],"exampleFix":"# before\ntext_fg_override_threshold 20pt\n# after\ntext_fg_override_threshold 20","handlingStrategy":"validation","validationCode":"def valid_unit(x: str, default_unit: str, extra: tuple) -> bool:\n    import re\n    m = re.match(r'^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(.*)$', x)\n    u = (m.group(1) if m else '') or default_unit\n    return u == default_unit or u in extra","typeGuard":null,"tryCatchPattern":"try:\n    number_with_unit(x, 'px')\nexcept ValueError:\n    x = strip_unit(x)  # fall back to default unit","preventionTips":["Learn each option's allowed units before adding suffixes","Omit the unit when unsure — the default applies"],"tags":["kitty","config","unit-validation","valueerror"],"backgroundTag":"invalid-config-value","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}