dgtlmoon/changedetection.io · error · ValueError
Invalid JSON object for field: {value}
Error message
Invalid JSON object for field: {value} What it means
This ValidationError is raised by the XPath validator in changedetectionio when lxml's tree.xpath() raises XPathEvalError while compiling a user-supplied XPath expression. It means the expression is syntactically invalid per the XPath 1.0 grammar that lxml/libxml2 supports. The message embeds both the bad expression and the underlying libxml2 error string.
Source
Thrown at changedetectionio/api/Import.py:78
else:
prop_type = None
# Handle array type (e.g., notification_urls)
if prop_type == 'array':
# Support both comma-separated and JSON array format
if value.startswith('['):
try:
return json.loads(value)
except json.JSONDecodeError:
return [v.strip() for v in value.split(',')]
return [v.strip() for v in value.split(',')]
# Handle object type (e.g., time_between_check, headers)
elif prop_type == 'object':
try:
return json.loads(value)
except json.JSONDecodeError:
raise ValueError(f"Invalid JSON object for field: {value}")
# Handle boolean type
elif prop_type == 'boolean':
return strtobool(value)
# Handle integer type
elif prop_type == 'integer':
return int(value)
# Handle number type (float)
elif prop_type == 'number':
return float(value)
# Default: return as string
return value
class Import(Resource):View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Fix the XPath syntax as reported in the embedded %(error)s text from libxml2
- Wrap browser-copied expressions: //tag[@class='x'] instead of CSS selectors
- Use 'css:' prefix in changedetectionio if you want CSS selectors instead of raw XPath
- Test the expression in a REPL: lxml.html.fromstring('<html></html>').xpath(expr)
Example fix
# before //div[@class='item # missing closing bracket # after //div[@class='item']
Defensive patterns
Strategy: validation
Validate before calling
from lxml import html, etree
def xpath_ok(expr: str) -> bool:
try:
tree = html.fromstring('<html></html>')
v = tree.xpath(expr)
return isinstance(v, list)
except (etree.XPathEvalError, etree.XPathSyntaxError):
return False
except Exception:
return False Type guard
def is_valid_xpath(expr: str) -> bool:
try:
html.fromstring('<html></html>').xpath(expr)
return True
except etree.XPathError:
return False Try / catch
try:
form.validate()
except ValidationError as e:
if 'not a valid XPath' in str(e):
# show embedded libxml2 detail to the user
... Prevention
- Run lxml .xpath() on a scratch document before submitting the form
- Use browser 'Copy XPath' then verify balanced quotes/brackets
- Prefer the css: prefix for CSS selectors instead of hand-writing XPath
When it happens
Trigger: Submitting a watch/filter form where a CSS/XPath-like field contains a line that lxml fails to compile, e.g. 'div[' (unclosed bracket), '///text()', or unsupported XPath 2.0 syntax like 'matches(...)' or 'if/then/else'. Each newline-separated line is stripped and compiled against an empty <html> doc under an lxml lock in forms.py __call__.
Common situations: Copy-pasting browser DevTools 'Copy XPath' output that contains quotes/newlines; using XPath 2.0+ functions unsupported by libxml2 (matches, lowercase, string-join); typos in filters like missing closing brackets; pasting CSS selectors (div.foo) instead of XPath (//div[@class='foo']).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- A system-error occurred when validating your XPath expressio
- Validation failed: {'; '.join(error_details)}
- Backup archive decompressed size ({total_uncompressed // (10
- XPath not permitted in this field!
- '%(expression)s' is not a valid XPath expression. (%(error)s
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/60ba44d2d8d780b4.
Report an issue: GitHub.