Bug description
Trying to upload an asset after sorting the asset list by the "last modified" column results in a server error. Afterwards, the asset list can no longer be viewed in the CP.
How to reproduce
- Set
'throw' => true on your filesystem
- Open asset overview in CP (/cp/assets/browse/assets)
- Sort by "Last Modifed" column (direction does not matter)
- Upload a new asset
- The asset upload fails
- Refresh the page: Loading the assets now results in an error, the list can no longer be displayed
We narrowed the issue down to the following:
- Statamic stores the currently used indexes in a stache entry "stache::indexes::assets::assets::_indexes". By default this key contains
["path", "folder", "basename"]
- When sorting the list by "Last Modifed", the stache entry is updated and now contains
["path", "folder", "last_modified"]
- When a new asset is saved, the indexes are updated before the metadata of the new asset are stored (https://github.com/statamic/cms/blob/5.x/src/Assets/AssetRepository.php#L148)
- When
last_modified is present in the currently used index list, the indexer tries to access lastModified() on the asset. This will try to read the metadata, which does not yet exist. This leads to an error.
- Since the error is not handled, the request will abort before the metadata for the new asset was stored, but after the asset itself was saved on the drive
- Reloading the asset list then errors out because of the missing metadata for an asset
I can think of a few different approaches to solve this, but I'm sure someone with more "under the hood" experience knows which one would be the proper way to handle this.
Each of these individually should fix the issue:
- Store asset metadata before updating the indexes
- Don't update the currently used indexes based on the sorting
- Handle the missing metadata in
lastModified() (return null?)
Logs
[2025-07-15 12:44:49] local.ERROR: Unable to read file from location: img/.meta/new-asset.jpg.yaml. Unable to read file from location: assets/img/.meta/new-asset.jpg.yaml. {"userId":"asdf","exception":"[object] (League\\Flysystem\\UnableToReadFile(code: 0): Unable to read file from location: img/.meta/new-asset.jpg.yaml. Unable to read file from location: assets/img/.meta/new-asset.jpg.yaml. at /Users/foobar/statamic-cms/vendor/league/flysystem/src/UnableToReadFile.php:24)
[stacktrace]
#0 /Users/foobar/statamic-cms/vendor/league/flysystem-path-prefixing/PathPrefixedAdapter.php(50): League\\Flysystem\\UnableToReadFile::fromLocation('img/.meta/jake-...', 'Unable to read ...', Object(League\\Flysystem\\UnableToReadFile))
#1 /Users/foobar/statamic-cms/vendor/league/flysystem/src/Filesystem.php(76): League\\Flysystem\\PathPrefixing\\PathPrefixedAdapter->read('img/.meta/jake-...')
#2 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(291): League\\Flysystem\\Filesystem->read('img/.meta/jake-...')
#3 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Filesystem/AbstractAdapter.php(14): Illuminate\\Filesystem\\FilesystemAdapter->get('img/.meta/jake-...')
#4 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(252): Statamic\\Filesystem\\AbstractAdapter->get('img/.meta/jake-...')
#5 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(468): Statamic\\Assets\\Asset->Statamic\\Assets\\{closure}()
#6 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php(453): Illuminate\\Cache\\Repository->rememberForever('asset-meta-asse...', Object(Closure))
#7 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(361): Illuminate\\Cache\\CacheManager->__call('rememberForever', Array)
#8 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(251): Illuminate\\Support\\Facades\\Facade::__callStatic('rememberForever', Array)
#9 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(264): Statamic\\Assets\\Asset->meta()
#10 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(229): Statamic\\Assets\\Asset->metaValue('last_modified')
#11 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(592): Statamic\\Assets\\Asset->meta('last_modified')
#12 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(1095): Statamic\\Assets\\Asset->lastModified()
#13 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Query/ResolveValue.php(52): Statamic\\Assets\\Asset->getQueryableValue('last_modified')
#14 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Query/ResolveValue.php(34): Statamic\\Query\\ResolveValue->getItemPartValue(Object(Statamic\\Assets\\Asset), 'last_modified')
#15 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Query/ResolveValue.php(22): Statamic\\Query\\ResolveValue->resolveItemPartValue(Object(Statamic\\Assets\\Asset), 'last_modified')
#16 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Stache/Indexes/Value.php(18): Statamic\\Query\\ResolveValue->__invoke(Object(Statamic\\Assets\\Asset), 'last_modified')
#17 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Stache/Indexes/Index.php(123): Statamic\\Stache\\Indexes\\Value->getItemValue(Object(Statamic\\Assets\\Asset))
#18 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Collections/HigherOrderCollectionProxy.php(65): Statamic\\Stache\\Indexes\\Index->updateItem(Object(Statamic\\Assets\\Asset))
#19 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(259): Illuminate\\Support\\HigherOrderCollectionProxy->Illuminate\\Support\\{closure}(Object(Statamic\\Stache\\Indexes\\Value), 'last_modified')
#20 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Collections/HigherOrderCollectionProxy.php(64): Illuminate\\Support\\Collection->each(Object(Closure))
#21 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Stache/Stores/BasicStore.php(122): Illuminate\\Support\\HigherOrderCollectionProxy->__call('updateItem', Array)
#22 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/AssetRepository.php(148): Statamic\\Stache\\Stores\\BasicStore->save(Object(Statamic\\Assets\\Asset))
#23 /Users/foobar/statamic-cms/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(361): Statamic\\Assets\\AssetRepository->save(Object(Statamic\\Assets\\Asset))
#24 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(629): Illuminate\\Support\\Facades\\Facade::__callStatic('save', Array)
#25 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Assets/Asset.php(918): Statamic\\Assets\\Asset->save()
#26 /Users/foobar/statamic-cms/vendor/statamic/cms/src/Http/Controllers/CP/Assets/AssetsController.php(118): Statamic\\Assets\\Asset->upload(Object(Illuminate\\Http\\UploadedFile))
[...]
Environment
Environment
Application Name: REPLACE_ME
Laravel Version: 11.45.1
PHP Version: 8.3.17
Composer Version: 2.8.3
Environment: local
Debug Mode: ENABLED
URL: localhost
Maintenance Mode: OFF
Timezone: UTC
Locale: de
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: redis
Database: sqlite
Logs: stack / daily
Mail: smtp
Queue: redis
Session: redis
Sentry
Enabled: MISSING DSN
Environment: local
Laravel SDK Version: 4.10.1
PHP SDK Version: 4.10.0
Release: 33ccfde
Sample Rate Errors: 100%
Sample Rate Performance Monitoring: 1%
Sample Rate Profiling: 1%
Send Default PII: ENABLED
Statamic
Addons: 5
Sites: 2 (🇩🇪 Deutsch, 🇫🇷 Français)
Stache Watcher: Enabled
Static Caching: Disabled
Version: 5.59.0 PRO
Statamic Addons
cnj/seotamic: 5.0.0
teamnovu/graphql-breadcrumbs: 1.0.7
teamnovu/localize: 5.0.0
teamnovu/statamic-gql-swr-cache: 1.0.0
xndbogdan/statamic-bard-text-color: 5.1.1
Installation
Fresh statamic/statamic site via CLI
Additional details
Assets are stored on an S3.
Also, this issue is probably related to #8641 .
Bug description
Trying to upload an asset after sorting the asset list by the "last modified" column results in a server error. Afterwards, the asset list can no longer be viewed in the CP.
How to reproduce
'throw' => trueon your filesystemWe narrowed the issue down to the following:
["path", "folder", "basename"]["path", "folder", "last_modified"]last_modifiedis present in the currently used index list, the indexer tries to accesslastModified()on the asset. This will try to read the metadata, which does not yet exist. This leads to an error.I can think of a few different approaches to solve this, but I'm sure someone with more "under the hood" experience knows which one would be the proper way to handle this.
Each of these individually should fix the issue:
lastModified()(return null?)Logs
Environment
Installation
Fresh statamic/statamic site via CLI
Additional details
Assets are stored on an S3.
Also, this issue is probably related to #8641 .