dgtlmoon/changedetection.io · warning
No Favicon available for {uuid}
Error message
No Favicon available for {uuid} What it means
Flask abort(404) raised by the watch favicon endpoint when no favicon file exists in the watch's data directory. changedetection.io stores a per-watch favicon (scraped or fetched) in watch.data_dir; when a browser requests /favicon/<uuid> and no such file has been saved yet, the handler falls through to this 404 with a descriptive message.
Source
Thrown at changedetectionio/api/Watch.py:459
watch = self.datastore.data['watching'].get(uuid)
if not watch:
abort(404, message=f"No watch exists with the UUID of {uuid}")
favicon_filename = watch.get_favicon_filename()
if favicon_filename:
# Use cached MIME type detection
filepath = os.path.join(watch.data_dir, favicon_filename)
mime = get_favicon_mime_type(filepath)
if 'text' in mime:
logger.debug(f"Aborting favicon request for {filepath} because mimetype might be text (bad mimetype) '{mime}'")
abort(404)
response = make_response(send_from_directory(watch.data_dir, favicon_filename))
response.headers['Content-type'] = mime
response.headers['Cache-Control'] = 'max-age=300, must-revalidate' # Cache for 5 minutes, then revalidate
return response
abort(404, message=f'No Favicon available for {uuid}')
class CreateWatch(Resource):
def __init__(self, **kwargs):
# datastore is a black box dependency
self.datastore = kwargs['datastore']
self.update_q = kwargs['update_q']
@auth.check_token
@validate_openapi_request('createWatch')
def post(self):
"""Create a single watch."""
# Silently discard `__`-prefixed transient/internal keys (not part of the public schema).
json_data = strip_internal_api_fields(request.get_json())
url = json_data['url'].strip()
if not is_safe_valid_url(url):View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Verify the watch has run at least one successful check so a favicon can be captured
- Check watch.data_dir on disk for the favicon file returned by watch.get_favicon_filename()
- Re-fetch the favicon by triggering a recheck of the watch
- If serving favicons is optional in your UI, tolerate 404 and render a placeholder icon
Example fix
# before
resp = requests.get(f'{base}/favicon/{uuid}')
resp.raise_for_status()
# after
resp = requests.get(f'{base}/favicon/{uuid}')
if resp.status_code == 404:
return placeholder_icon # favicon not yet captured
resp.raise_for_status() Defensive patterns
Strategy: fallback
Validate before calling
import os, requests
def favicon_exists(base, uuid):
# cheap probe: 404 means not captured yet
return requests.head(f'{base}/favicon/{uuid}').status_code == 200 Try / catch
try:
resp = requests.get(f'{base}/favicon/{uuid}', timeout=10)
resp.raise_for_status()
except requests.HTTPError as e:
if e.response.status_code == 404:
return DEFAULT_ICON
raise Prevention
- Run at least one check per watch before expecting favicons
- Cache 404 results briefly so UIs don't re-request missing favicons
- Keep watch data dirs intact when migrating instances
When it happens
Trigger: GET request to the watch favicon URL (e.g. /favicon/<uuid>) before any favicon was captured for the watch, after the favicon file was deleted from disk (data dir pruned/migrated), or when the fetch of the favicon failed during watch checks.
Common situations: Freshly created watches that have never run a check; watches whose data_dir was copied/restored without favicon files; watchdog/browserless not running so favicons never get captured.
Related errors
- Processor '{processor_name}' does not provide difference dat
- abort(404)
- abort(404)
- Processor '{processor_name}' does not support xlsx export
- Asset '{asset_name}' not found
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/fc439f69d05d07e7.
Report an issue: GitHub.