{"record":{"id":"1b859a04be72f80b","repo":"dgtlmoon/changedetection.io","slug":"bounding-box-values-must-be-non-negative","errorCode":null,"errorMessage":"Bounding box values must be non-negative","messagePattern":"Bounding box values must be non-negative","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"warning","filePath":"changedetectionio/processors/image_ssim_diff/forms.py","lineNumber":29,"sourceCode":"\n\ndef validate_bounding_box(form, field):\n    \"\"\"Validate bounding box format: x,y,width,height with integers.\"\"\"\n    if not field.data:\n        return  # Optional field\n\n    if len(field.data) > 100:\n        raise ValidationError(_l('Bounding box value is too long'))\n\n    # Should be comma-separated integers\n    if not re.match(r'^\\d+,\\d+,\\d+,\\d+$', field.data):\n        raise ValidationError(_l('Bounding box must be in format: x,y,width,height (integers only)'))\n\n    # Validate values are reasonable (not negative, not ridiculously large)\n    parts = [int(p) for p in field.data.split(',')]\n    for part in parts:\n        if part < 0:\n            raise ValidationError(_l('Bounding box values must be non-negative'))\n        if part > 10000:  # Reasonable max screen dimension\n            raise ValidationError(_l('Bounding box values are too large'))\n\n\ndef validate_selection_mode(form, field):\n    \"\"\"Validate selection mode value.\"\"\"\n    if not field.data:\n        return  # Optional field\n\n    if field.data not in ['element', 'draw']:\n        raise ValidationError(_l('Selection mode must be either \"element\" or \"draw\"'))\n\n\nclass processor_settings_form(processor_text_json_diff_form):\n    \"\"\"Form for fast image comparison processor settings.\"\"\"\n\n    processor_config_min_change_percentage = IntegerField(\n        _l('Minimum Change Percentage'),","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/processors/image_ssim_diff/forms.py#L11-L47","documentation":"After the format regex passes, the validator splits the value and rejects any component less than 0. In practice this branch is nearly unreachable because the regex \\d+ already forbids minus signs — it exists as defence-in-depth against refactors of the regex.","triggerScenarios":"Only reachable if the format regex is relaxed (e.g. to allow signed ints) or the validator is reused with different pre-checks; with the shipped regex, '-10,20,300,400' fails earlier at the format check, not here.","commonSituations":"Custom forks that loosen the regex to accept '+/'-prefixed numbers; copy-pasting this validator into other projects without keeping the \\d+ regex in sync.","solutions":["Keep the strict ^\\d+,\\d+,\\d+,\\d+$ regex so negative values are rejected earlier","If you fork/relax the regex, keep this non-negative check in place","Clamp or reject negative coordinates at the source (region-selection UI)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"parts = [int(p) for p in bbox.split(',')]\nassert all(p >= 0 for p in parts)","typeGuard":"def bbox_components_non_negative(s: str) -> bool:\n    return all(int(p) >= 0 for p in s.split(','))","tryCatchPattern":null,"preventionTips":["Keep the strict \\\\d+ regex in sync with this check when forking","Reject negative coordinates at the selection UI level"],"tags":["wtforms","validation","bounding-box","defensive-check"],"backgroundTag":"form-validation-failed","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}