{"record":{"id":"6bdfc04cd4dad039","repo":"dgtlmoon/changedetection.io","slug":"asset-asset-name-not-found","errorCode":null,"errorMessage":"Asset '{asset_name}' not found","messagePattern":"Asset '(.+?)' not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"changedetectionio/blueprint/ui/diff.py","lineNumber":614,"sourceCode":"        # Get the processor type for this watch\n        processor_name = watch.get('processor', 'text_json_diff')\n\n        # Try to get the processor's difference module (works for both built-in and plugin processors)\n        from changedetectionio.processors import get_processor_submodule\n        processor_module = get_processor_submodule(processor_name, 'difference')\n\n        # Call the processor's get_asset() function\n        if processor_module and hasattr(processor_module, 'get_asset'):\n            result = processor_module.get_asset(\n                asset_name=asset_name,\n                watch=watch,\n                datastore=datastore,\n                request=request\n            )\n\n            if result is None:\n                from flask import abort\n                abort(404, description=f\"Asset '{asset_name}' not found\")\n\n            binary_data, content_type, cache_control = result\n\n            response = make_response(binary_data)\n            response.headers['Content-Type'] = content_type\n            if cache_control:\n                response.headers['Cache-Control'] = cache_control\n            return response\n        else:\n            logger.warning(f\"Processor {processor_name} does not implement get_asset()\")\n            from flask import abort\n            abort(404, description=f\"Processor '{processor_name}' does not support assets\")\n\n    return diff_blueprint\n","sourceCodeStart":596,"sourceCodeEnd":629,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/blueprint/ui/diff.py#L596-L629","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\nresp = requests.get(f'{base}/diff/{uuid}/asset/last-screenshot.png')\nresp.raise_for_status()\n\n# after\nresp = requests.get(f'{base}/diff/{uuid}/asset/last-screenshot.png')\nif resp.status_code == 404:\n    trigger_recheck(uuid); time.sleep(poll_interval)\nresp.raise_for_status()","handlingStrategy":"fallback","validationCode":"import os\ndef asset_exists(watch, asset_name):\n    # processor assets typically live in the watch data dir\n    return os.path.isfile(os.path.join(watch.data_dir, asset_name))","typeGuard":null,"tryCatchPattern":"try:\n    r = requests.get(asset_url)\n    r.raise_for_status()\nexcept requests.HTTPError as e:\n    if e.response.status_code == 404:\n        return None  # asset not present for this watch\n    raise","preventionTips":["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"],"tags":["flask","processor-plugin","asset","http-404"],"backgroundTag":"http-404-not-found","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}