dgtlmoon/changedetection.io · warning · ValidationError
Selection mode must be either "element" or "draw"
Error message
Selection mode must be either "element" or "draw"
What it means
This is a WTForms ValidationError raised by the custom validator validate_selection_mode in the image_ssim_diff processor settings form. It fires when the submitted selection_mode field is non-empty but is not one of the two allowed literal values ('element' or 'draw'). It exists to stop invalid crop/selection modes from reaching the screenshot-diff processor.
Source
Thrown at changedetectionio/processors/image_ssim_diff/forms.py:40
if not re.match(r'^\d+,\d+,\d+,\d+$', field.data):
raise ValidationError(_l('Bounding box must be in format: x,y,width,height (integers only)'))
# Validate values are reasonable (not negative, not ridiculously large)
parts = [int(p) for p in field.data.split(',')]
for part in parts:
if part < 0:
raise ValidationError(_l('Bounding box values must be non-negative'))
if part > 10000: # Reasonable max screen dimension
raise ValidationError(_l('Bounding box values are too large'))
def validate_selection_mode(form, field):
"""Validate selection mode value."""
if not field.data:
return # Optional field
if field.data not in ['element', 'draw']:
raise ValidationError(_l('Selection mode must be either "element" or "draw"'))
class processor_settings_form(processor_text_json_diff_form):
"""Form for fast image comparison processor settings."""
processor_config_min_change_percentage = IntegerField(
_l('Minimum Change Percentage'),
validators=[
validators.Optional(),
validators.NumberRange(min=1, max=100, message=_l('Must be between 0 and 100'))
],
render_kw={"placeholder": "Use global default (0.1)"}
)
processor_config_pixel_difference_threshold_sensitivity = SelectField(
_l('Pixel Difference Sensitivity'),
choices=[
('', _l('Use global default'))View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Set selection_mode to exactly 'element' or 'draw' (case-sensitive, lowercase)
- Leave the field empty/omitted if you don't need a selection mode
- If you added a new mode in a fork, extend the allowed list in validate_selection_mode in changedetectionio/processors/image_ssim_diff/forms.py:40
Example fix
// before
form_data = {'selection_mode': 'crop'}
// after
form_data = {'selection_mode': 'draw'} Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = {'element', 'draw', ''}
if form_data.get('selection_mode', '') not in ALLOWED:
raise ValueError("selection_mode must be 'element' or 'draw'") Type guard
def is_valid_selection_mode(v: str) -> bool:
return v in ('element', 'draw') Prevention
- Use a dropdown/radio with only 'element' and 'draw' in custom UIs instead of free text
- Keep the field omitted when unused — empty is valid
When it happens
Trigger: POSTing the processor settings form with selection_mode set to anything other than 'element' or 'draw' (e.g. 'freehand', 'crop', 'rect'). Only triggers when field.data is truthy — an empty value passes silently because the field is optional.
Common situations: Custom UI code or API clients writing the form directly; older frontends submitting a legacy mode name after an upgrade; hand-crafted curl/pytest form posts that guess the allowed values.
Related errors
- Invalid JSON object for field: {value}
- Backup archive decompressed size ({total_uncompressed // (10
- Zip Slip path traversal detected in backup archive: {member.
- BrowserStepsStepException
- Non200ErrorCodeReceived
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/ce0a21556f8a29ea.
Report an issue: GitHub.