Repository navigation
Conversation
A cached container listing can still name a file that is no longer on disk. Reading that asset asked Flysystem for its size and threw, and the path was still handed back as the current asset.
reconcile() drops a listed path whose file is gone. exists() stays a listing lookup, so callers can tell those two steps apart.
The file metadata is only merged after those reads succeed, so a throw leaves the original data array for the existing return.
A missing file is dropped during meta generation. writeMeta() now checks the listing itself, so no caller can save a meta file for that path.
The repository delete updates the listing and the asset index without reading metadata, so it never calls forgetMissingFile() again.
A Stache asset is not missing just because the container listing does not name it yet. Only a listed path whose file is gone should be reconciled and dropped.
The asset repository's eloquent delete removes the meta row. Forget the cached path directly so a missing file no longer takes authored data with it.
A timeout or a 403 throws the same metadata exceptions as a missing file. Only drop the path when the disk reports it missing, and leave a failed read uncached so the next request can try again.
A missing file is dropped when its metadata is generated. Lookups and queries only need the listing, so the public reconcile method can go.
Drop assertions that only described behavior removed before the pull request, and name the remaining tests like the rest of the file.
A warm meta cache never reaches generateMeta(), so a deleted file stayed in the listing after the thumbnail 404'd.
aerni
marked this pull request as ready for review
November 11, 2026 11:15
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The diff includes #15833 because this has to target
6.x. That branch only exists on the fork, so it can't be the base here. The new change is f22809b.Issue
#15833 drops a listed asset when a metadata read finds the file gone. That happens in
generateMeta(). With a warm meta cache the size and mime type are already stored, so opening the asset never callsgenerateMeta()and the path stays in the cached directory listing.The Control Panel builds the folder from that listing. The thumbnail is a later request. It opens the file, Glide fails, and the response is a 404. The row is still there on the next load.
Solution
This builds on #15833. When image generation reports the source missing, confirm the file is gone with
disk()->exists(), then callforgetMissingFile()from that PR. The path leaves the listing and, unless assets use the eloquent driver, the Stache index. Stored asset data stays put: the.metafile and an eloquent meta row are left alone.The folder response already sent still includes the row. The next load omits it. A cached manipulation never opens the source, so the path remains until that cache misses and a generation confirms the file is missing. An existence check that throws, such as a timeout or a 403, propagates and leaves the listing unchanged.