{"record":{"id":"89b0de5df4840e3c","repo":"Textualize/textual","slug":"value-does-not-match-template","errorCode":null,"errorMessage":"Value does not match template!","messagePattern":"Value does not match template!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/textual/widgets/_masked_input.py","lineNumber":511,"sourceCode":"            classes=classes,\n            disabled=disabled,\n            compact=compact,\n        )\n\n        self._template = _Template(self, template)\n        self.template = template\n\n        value, _ = self._template.insert_separators(value or \"\", 0)\n        self.value = value\n        if tooltip is not None:\n            self.tooltip = tooltip\n\n    def validate_value(self, value: str) -> str:\n        \"\"\"Validates value against template.\"\"\"\n        if self._template is None:\n            return value\n        if not self._template.check(value, True):\n            raise ValueError(\"Value does not match template!\")\n        return value[: len(self._template.mask)]\n\n    def _watch_template(self, template: str) -> None:\n        \"\"\"Revalidate when template changes.\"\"\"\n        self._template = _Template(self, template) if template else None\n        if self.is_mounted:\n            self._watch_value(self.value)\n\n    def _watch_placeholder(self, placeholder: str) -> None:\n        \"\"\"Update template display mask when placeholder changes.\"\"\"\n        if self._template is not None:\n            self._template.update_mask(placeholder)\n            self.refresh()\n\n    def validate(self, value: str) -> ValidationResult | None:\n        \"\"\"Run all the validators associated with this MaskedInput on the supplied value.\n\n        Same as `Input.validate()` but also validates against template which acts as an","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widgets/_masked_input.py#L493-L529","documentation":"A ValueError raised by MaskedInput.validate_value when a reactive value does not satisfy the current _template.check(). It signals that the widget's value was set programmatically (or via reactive update) to a string that does not fit the mask, e.g. wrong length or characters in wrong slots.","triggerScenarios":"Setting masked_input.value = '123' when the template is '999-9999'; assigning a value saved from a different template before the template reactive updates; programmatically populating from a database field with inconsistent formatting.","commonSituations":"Loading stored values into an editing form where old data doesn't match the current mask; changing the template reactive while an old value remains; trimming/normalizing values incorrectly before assignment.","solutions":["Format the value to the template before assigning (correct length and slot characters).","When changing templates, also set a compatible value in the same update.","Sanitize loaded data (strip separators, re-pad) or leave value empty and prefill via user/default handling.","Catch ValueError around programmatic value assignment during data load."],"exampleFix":"# before\nmasked.value = '1234567890'  # template '999-9999'\n\n# after\nmasked.value = '123-4567'  # matches template","handlingStrategy":"validation","validationCode":"if masked.template and len(masked.value.replace(masked.blank, '')) != expected_len:\n    masked.value = ''  # reset instead of assigning mismatched value","typeGuard":null,"tryCatchPattern":"try:\n    masked.value = loaded_value\nexcept ValueError:\n    masked.value = ''","preventionTips":["Format stored data to the mask before assignment","Update value together with template changes","Sanitize/strip separators when loading from databases"],"tags":["textual","masked-input","value-error","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}