dgtlmoon/changedetection.io · warning
Asset '{asset_name}' not found
Error message
Asset '{asset_name}' not found What it means
abort(404) in the processor asset endpoint when the processor's get_asset() hook ran successfully but returned None, meaning the named asset does not exist for that watch. Assets are processor-served binaries (e.g. last screenshot, embedded media) resolved by name per watch.
Source
Thrown at changedetectionio/blueprint/ui/diff.py:614
# Get the processor type for this watch
processor_name = watch.get('processor', 'text_json_diff')
# Try to get the processor's difference module (works for both built-in and plugin processors)
from changedetectionio.processors import get_processor_submodule
processor_module = get_processor_submodule(processor_name, 'difference')
# Call the processor's get_asset() function
if processor_module and hasattr(processor_module, 'get_asset'):
result = processor_module.get_asset(
asset_name=asset_name,
watch=watch,
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
- Trigger a recheck so the processor regenerates the asset
- Verify the exact asset name from the watch's current data (not from an outdated UI cache)
- Check the watch's data dir on disk to confirm the asset file exists
Example fix
# before
resp = requests.get(f'{base}/diff/{uuid}/asset/last-screenshot.png')
resp.raise_for_status()
# after
resp = requests.get(f'{base}/diff/{uuid}/asset/last-screenshot.png')
if resp.status_code == 404:
trigger_recheck(uuid); time.sleep(poll_interval)
resp.raise_for_status() Defensive patterns
Strategy: fallback
Validate before calling
import os
def asset_exists(watch, asset_name):
# processor assets typically live in the watch data dir
return os.path.isfile(os.path.join(watch.data_dir, asset_name)) Try / catch
try:
r = requests.get(asset_url)
r.raise_for_status()
except requests.HTTPError as e:
if e.response.status_code == 404:
return None # asset not present for this watch
raise Prevention
- Re-check the watch before expecting assets
- Derive asset names from current watch state, not cached pages
- Handle 404 as an expected 'no asset yet' state in UIs
When it happens
Trigger: GET /diff/<uuid>/asset/<asset_name> where the processor has get_asset() but no asset with that name exists (never captured, deleted, or wrong name such as a stale filename from history).
Common situations: Requesting a screenshot/asset before the first successful check; referencing an asset name from an old snapshot after files were pruned; changing processors so old asset names are no longer produced.
Related errors
- Processor '{processor_name}' does not support assets
- 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/6bdfc04cd4dad039.
Report an issue: GitHub.