dgtlmoon/changedetection.io · warning · ValidationError
Invalid value.
Error message
Invalid value.
What it means
The same line-by-line validator raises ValidationError when a non-empty line fails to match the validator's compiled regex pattern. Each stripped line must fully match self.pattern (typically via re.match).
Source
Thrown at changedetectionio/forms.py:818
if not data:
return
# normalize into list of lines
if isinstance(data, str) and self.split_lines:
lines = data.splitlines()
elif isinstance(data, (list, tuple)):
lines = data
else:
lines = [data]
for line in lines:
stripped = line.strip()
if not stripped:
if self.allow_empty:
continue
raise ValidationError(self.message or _l("Empty value not allowed."))
if not self.pattern.match(stripped):
raise ValidationError(self.message or _l("Invalid value."))
def visual_browser_choices():
"""Browsers that can render the Add-Watch live preview, as RadioField choices.
Lazy import (the add_watch_ui blueprint imports this module) and empty outside an
app context, because WTForms evaluates a choices callable on field construction.
"""
from flask import current_app, has_app_context
from changedetectionio.blueprint.add_watch_ui import browser_config
if not has_app_context():
return []
datastore = current_app.config.get('DATASTORE')
return browser_config.radio_choices(datastore) if datastore else []
class quickWatchForm(Form):
url = StringField('URL', validators=[validateURL()])View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Check the pattern the field was constructed with and correct the offending line
- Strip or normalize pasted text (remove smart quotes, BOMs, non-breaking spaces) before submitting
- Test each line individually against the pattern to find the failing entry
Example fix
# before pattern = re.compile(r'^\w+$') # after pattern = re.compile(r'^[\w-]+$') # allow dashes if values contain them
Defensive patterns
Strategy: validation
Validate before calling
import re
pattern = re.compile(r'^\w+$') # use the same pattern as the validator
bad = [l.strip() for l in value.splitlines() if l.strip() and not pattern.match(l.strip())]
assert not bad, f'Lines failing pattern: {bad}' Type guard
def lines_match(value: str, pattern: re.Pattern) -> bool:
return all(pattern.match(l.strip()) for l in value.splitlines() if l.strip()) Prevention
- Test each line against the field's regex before submit
- Normalize pasted text (strip smart quotes/BOMs/non-breaking spaces)
When it happens
Trigger: Entering a line containing characters or a format not matching the pattern passed to the validator (e.g. whitespace inside a token, wrong scheme in a URL, non-numeric value) in a field using this validator class.
Common situations: Paste of values with invisible Unicode characters (non-breaking spaces, BOM); regex expecting ^https?:// and user entering bare domains; locale/keyboard producing different dash or quote characters.
Related errors
- RegEx '%s' is not a valid regular expression.
- Empty value not allowed.
- Bounding box must be in format: x,y,width,height (integers o
- Bounding box value is too long
- Bounding box values must be non-negative
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/8c8d4d9b9646421b.
Report an issue: GitHub.