You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the {{ glide }} tag is given an asset URL (or path) that Asset::find() cannot resolve, but the file itself is readable on the container disk, the tag does not skip the image. It passes null into ImageGenerator::generateByAsset(), which immediately calls $asset->isVideo():
// src/Imaging/ImageGenerator.php:156-164publicfunction generateByAsset($asset, array$params)
{
if (ThumbnailExtractor::available() && $asset->isVideo()) {
// ...
}
if ($asset->isVideo()) {
return'';
}
That throws Error: Call to a member function isVideo() on null. Because it is an \Error and not an \Exception, it escapes the tag's own error handling in Glide::generate():
So one unresolvable asset takes down the entire page with a 500 instead of rendering without that image. Every other failure mode in this closure (unreadable file, invalid manipulation, etc.) is an \Exception and degrades gracefully; only the "repository returned null" case is fatal.
Expected: an asset that cannot be resolved is logged and skipped, like every other error inside the tag. Actual: the whole request fails with Call to a member function isVideo() on null.
How to reproduce
Any situation where the file exists on the container disk but the asset repository returns null for its URL. The concrete case we hit in production:
Statamic 6.31 with statamic/eloquent-driver 5.11 for assets.
Upload an asset with a space, parenthesis or @ in its filename, e.g. logo (1).png. Since [6.x] Encode asset URLs #15146 its URL is /assets/logo%20%281%29.png.
Render {{ glide src="/assets/logo%20%281%29.png" width="100" }}{{ url }}{{ /glide }} — or simply any page whose og:image (SEO Pro) or content references that asset.
Result: 500, Call to a member function isVideo() on null, vendor/statamic/cms/src/Imaging/ImageGenerator.php:158.
The driver bug is being fixed upstream, but the tag's behaviour is the part that turned a missing image into a site-wide outage (75 occurrences across all tenants of a multi-site install within a day). The same fatal should be reachable without the Eloquent driver: #15146 notes that an old, unencoded URL to a file whose name contains a literal % no longer resolves via findByUrl(), while the file itself is still readable at that path. (I could not verify that variant in my environment, so treat it as a plausible second trigger rather than a confirmed one.)
Minimal call that shows the fatal directly:
app(\Statamic\Imaging\ImageGenerator::class)->generateByAsset(null, []);
// Error: Call to a member function isVideo() on null @ ImageGenerator.php:158
Logs
Error: Call to a member function isVideo() on null
#0 vendor/statamic/cms/src/Imaging/ImageGenerator.php:158 Statamic\Imaging\ImageGenerator::generateByAsset()
#1 vendor/statamic/cms/src/Tags/Glide.php:180 Statamic\Tags\Glide::generateImage()
#2 vendor/statamic/cms/src/Tags/Glide.php:139 Statamic\Tags\Glide::{closure}()
#3 vendor/laravel/framework/src/Illuminate/Collections/Arr.php:858 Illuminate\Support\Arr::map()
#4 vendor/laravel/framework/src/Illuminate/Collections/Collection.php:831 Illuminate\Support\Collection::map()
#5 vendor/statamic/cms/src/Tags/Glide.php:134 Statamic\Tags\Glide::generate()
#6 vendor/statamic/cms/src/Tags/Glide.php:54 Statamic\Tags\Glide::index()
#7 vendor/statamic/cms/src/View/Antlers/Language/Runtime/NodeProcessor.php:1658 ...
Existing Laravel app (multi-tenant, one codebase serving several sites).
Additional details
Suggested fix, either or both:
In Glide::generateImage(), return early (or throw an \Exception) when Asset::find($item) is null, so the tag's existing catch (\Exception) handles it and the image is skipped with a log line.
In ImageGenerator::generateByAsset(), guard against a null asset with a descriptive exception instead of dereferencing it.
Happy to open a PR for either if you have a preference.
Bug description
When the
{{ glide }}tag is given an asset URL (or path) thatAsset::find()cannot resolve, but the file itself is readable on the container disk, the tag does not skip the image. It passesnullintoImageGenerator::generateByAsset(), which immediately calls$asset->isVideo():That throws
Error: Call to a member function isVideo() on null. Because it is an\Errorand not an\Exception, it escapes the tag's own error handling inGlide::generate():So one unresolvable asset takes down the entire page with a 500 instead of rendering without that image. Every other failure mode in this closure (unreadable file, invalid manipulation, etc.) is an
\Exceptionand degrades gracefully; only the "repository returned null" case is fatal.Expected: an asset that cannot be resolved is logged and skipped, like every other error inside the tag.
Actual: the whole request fails with
Call to a member function isVideo() on null.How to reproduce
Any situation where the file exists on the container disk but the asset repository returns
nullfor its URL. The concrete case we hit in production:statamic/eloquent-driver5.11 for assets.@in its filename, e.g.logo (1).png. Since [6.x] Encode asset URLs #15146 its URL is/assets/logo%20%281%29.png.findByUrl()does not decode the path (findByUrl() does not decode percent-encoded paths, returning null for filenames with spaces, parentheses or @ eloquent-driver#609, fix in Decode percent-encoded paths inAssetRepository::findByUrl()eloquent-driver#610), soAsset::find('/assets/logo%20%281%29.png')returnsnull.{{ glide src="/assets/logo%20%281%29.png" width="100" }}{{ url }}{{ /glide }}— or simply any page whoseog:image(SEO Pro) or content references that asset.Call to a member function isVideo() on null,vendor/statamic/cms/src/Imaging/ImageGenerator.php:158.The driver bug is being fixed upstream, but the tag's behaviour is the part that turned a missing image into a site-wide outage (75 occurrences across all tenants of a multi-site install within a day). The same fatal should be reachable without the Eloquent driver: #15146 notes that an old, unencoded URL to a file whose name contains a literal
%no longer resolves viafindByUrl(), while the file itself is still readable at that path. (I could not verify that variant in my environment, so treat it as a plausible second trigger rather than a confirmed one.)Minimal call that shows the fatal directly:
Logs
Environment
Statamic 6.31.0 (Pro), Laravel 13.26.1, PHP 8.4.17, statamic/eloquent-driver 5.11.0, statamic/seo-pro 7.13.3, Antlers runtime parser.
Installation
Existing Laravel app (multi-tenant, one codebase serving several sites).
Additional details
Suggested fix, either or both:
Glide::generateImage(), return early (or throw an\Exception) whenAsset::find($item)isnull, so the tag's existingcatch (\Exception)handles it and the image is skipped with a log line.ImageGenerator::generateByAsset(), guard against anullasset with a descriptive exception instead of dereferencing it.Happy to open a PR for either if you have a preference.