dgtlmoon/changedetection.io · error
Processor '{processor_name}' does not support assets
Error message
Processor '{processor_name}' does not support assets What it means
abort(404) raised when the processor serving /diff/<uuid>/asset/... does not implement the get_asset() hook at all. The endpoint checks hasattr(processor_module, 'get_asset'); text-based processors typically don't provide binary assets, so any asset request against them 404s with this description and a server-side warning log.
Source
Thrown at changedetectionio/blueprint/ui/diff.py:626
datastore=datastore,
request=request
)
if result is None:
from flask import abort
abort(404, description=f"Asset '{asset_name}' not found")
binary_data, content_type, cache_control = result
response = make_response(binary_data)
response.headers['Content-Type'] = content_type
if cache_control:
response.headers['Cache-Control'] = cache_control
return response
else:
logger.warning(f"Processor {processor_name} does not implement get_asset()")
from flask import abort
abort(404, description=f"Processor '{processor_name}' does not support assets")
return diff_blueprint
View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Only request assets from processors that implement get_asset (e.g. visual/screenshot-capable ones)
- Enable the screenshot/visual mode for the watch if you need screenshot assets
- For custom processors, implement get_asset(watch, datastore, request, asset_name) returning (binary_data, content_type, cache_control) or None
Example fix
# before (custom processor lacking the hook)
# requests.get(f'{base}/diff/{uuid}/asset/screenshot.png') -> 404
# after
def get_asset(watch, datastore, request, asset_name):
p = os.path.join(watch.data_dir, asset_name)
if not os.path.isfile(p):
return None
return open(p,'rb').read(), 'image/png', 'max-age=60' Defensive patterns
Strategy: type-guard
Validate before calling
from changedetectionio.processors import get_processor_submodule
def processor_serves_assets(name):
m = get_processor_submodule(name, 'difference') or get_processor_submodule(name, None)
return m is not None and hasattr(m, 'get_asset') Type guard
def has_get_asset(processor_module) -> bool:
"""True when the processor can serve binary assets."""
return callable(getattr(processor_module, 'get_asset', None)) Try / catch
if not hasattr(processor_module, 'get_asset'):
logger.warning(f"Processor {processor_name} does not implement get_asset()")
abort(404, description=f"Processor '{processor_name}' does not support assets") Prevention
- Advertise asset support in processor metadata and check it in the UI
- Implement get_asset() in custom processors that manage binary artifacts
- Don't assume screenshot-style assets exist for text processors
When it happens
Trigger: GET /diff/<uuid>/asset/<name> for a watch whose processor module has no get_asset function; also when the processor name resolves to a module without the hook (lookup returns a module but the attribute check fails).
Common situations: UI or scripts assuming all processors serve screenshots; custom processors that never implemented get_asset; after changing a watch's processor type, stale links still point at the asset route.
Related errors
- Asset '{asset_name}' not found
- Asset '{asset_name}' not found
- Processor '{processor_name}' does not support assets
- Processor '{processor_name}' does not provide difference dat
- Processor '{processor_name}' does not support xlsx export
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/56ea1345db758f05.
Report an issue: GitHub.