Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to 11.10 from 11.9.2 breaking with error "There is no conversion named thumb" #3724

Open
SlyDave opened this issue Nov 14, 2024 · 4 comments

Comments

@SlyDave
Copy link
Contributor

SlyDave commented Nov 14, 2024

On 11.9.2 everything works.

On 11.10, the following error occurs when updating or saving media:

{
    "message": "There is no conversion named `thumb`",
    "exception": "Spatie\\MediaLibrary\\MediaCollections\\Exceptions\\InvalidConversion",
    "file": "C:\\www\\workrest\\vendor\\spatie\\laravel-medialibrary\\src\\MediaCollections\\Exceptions\\InvalidConversion.php",
    "line": 11,
    "trace": [
        {
            "file": "C:\\www\\workrest\\vendor\\spatie\\laravel-medialibrary\\src\\Conversions\\ConversionCollection.php",
            "line": 46,
            "function": "unknownName",
            "class": "Spatie\\MediaLibrary\\MediaCollections\\Exceptions\\InvalidConversion",
            "type": "::"
        },
        {
            "file": "C:\\www\\workrest\\app\\Services\\MediaLibrary\\Filesystem.php",
            "line": 21,
            "function": "getByName",
            "class": "Spatie\\MediaLibrary\\Conversions\\ConversionCollection",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\spatie\\laravel-medialibrary\\src\\MediaCollections\\Filesystem.php",
            "line": 259,
            "function": "renameConversionFiles",
            "class": "App\\Services\\MediaLibrary\\Filesystem",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\spatie\\laravel-medialibrary\\src\\MediaCollections\\Models\\Observers\\MediaObserver.php",
            "line": 30,
            "function": "syncFileNames",
            "class": "Spatie\\MediaLibrary\\MediaCollections\\Filesystem",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Events\\Dispatcher.php",
            "line": 478,
            "function": "updating",
            "class": "Spatie\\MediaLibrary\\MediaCollections\\Models\\Observers\\MediaObserver",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Events\\Dispatcher.php",
            "line": 286,
            "function": "Illuminate\\Events\\{closure}",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Events\\Dispatcher.php",
            "line": 266,
            "function": "invokeListeners",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Events\\Dispatcher.php",
            "line": 232,
            "function": "dispatch",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Concerns\\HasEvents.php",
            "line": 215,
            "function": "until",
            "class": "Illuminate\\Events\\Dispatcher",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Model.php",
            "line": 1221,
            "function": "fireModelEvent",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Model.php",
            "line": 1155,
            "function": "performUpdate",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\app\\Models\\User.php",
            "line": 390,
            "function": "save",
            "class": "Illuminate\\Database\\Eloquent\\Model",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\app\\LegacyAPI\\Controllers\\UsersController.php",
            "line": 86,
            "function": "updateSignature",
            "class": "App\\Models\\User",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Concerns\\ManagesTransactions.php",
            "line": 32,
            "function": "App\\LegacyAPI\\Controllers\\{closure}",
            "class": "App\\LegacyAPI\\Controllers\\UsersController",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\DatabaseManager.php",
            "line": 471,
            "function": "transaction",
            "class": "Illuminate\\Database\\Connection",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Facades\\Facade.php",
            "line": 358,
            "function": "__call",
            "class": "Illuminate\\Database\\DatabaseManager",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\app\\LegacyAPI\\Controllers\\UsersController.php",
            "line": 79,
            "function": "__callStatic",
            "class": "Illuminate\\Support\\Facades\\Facade",
            "type": "::"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Controller.php",
            "line": 54,
            "function": "update",
            "class": "App\\LegacyAPI\\Controllers\\UsersController",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php",
            "line": 43,
            "function": "callAction",
            "class": "Illuminate\\Routing\\Controller",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
            "line": 264,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\ControllerDispatcher",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
            "line": 210,
            "function": "runController",
            "class": "Illuminate\\Routing\\Route",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
            "line": 808,
            "function": "run",
            "class": "Illuminate\\Routing\\Route",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 144,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\app\\Http\\Middleware\\JsonResponseMiddleware.php",
            "line": 15,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "App\\Http\\Middleware\\JsonResponseMiddleware",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\SubstituteBindings.php",
            "line": 51,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Routing\\Middleware\\SubstituteBindings",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php",
            "line": 161,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php",
            "line": 127,
            "function": "handleRequest",
            "class": "Illuminate\\Routing\\Middleware\\ThrottleRequests",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php",
            "line": 89,
            "function": "handleRequestUsingNamedLimiter",
            "class": "Illuminate\\Routing\\Middleware\\ThrottleRequests",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Routing\\Middleware\\ThrottleRequests",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Auth\\Middleware\\Authenticate.php",
            "line": 64,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Auth\\Middleware\\Authenticate",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 119,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
            "line": 807,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
            "line": 786,
            "function": "runRouteWithinStack",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
            "line": 750,
            "function": "runRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
            "line": 739,
            "function": "dispatchToRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
            "line": 201,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 144,
            "function": "Illuminate\\Foundation\\Http\\{closure}",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\nova\\src\\Http\\Middleware\\ServeNova.php",
            "line": 23,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Laravel\\Nova\\Http\\Middleware\\ServeNova",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull.php",
            "line": 31,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php",
            "line": 51,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\ValidatePostSize.php",
            "line": 27,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\ValidatePostSize",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php",
            "line": 110,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\HandleCors.php",
            "line": 62,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\HandleCors",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\TrustProxies.php",
            "line": 58,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\TrustProxies",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks.php",
            "line": 22,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 183,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
            "line": 119,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
            "line": 176,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
            "line": 145,
            "function": "sendRequestThroughRouter",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Application.php",
            "line": 1190,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "C:\\www\\workrest\\public\\index.php",
            "line": 17,
            "function": "handleRequest",
            "class": "Illuminate\\Foundation\\Application",
            "type": "->"
        },
        {
            "file": "C:\\Program Files\\Herd\\resources\\app.asar.unpacked\\resources\\valet\\server.php",
            "line": 139,
            "function": "require"
        }
    ]
}
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('avatar')
            ->acceptsMimeTypes(['image/jpg', 'image/jpeg', 'image/png', 'image/webp'])
            ->singleFile()
            ->useDisk(config('filesystems.avatars'));

        $this->addMediaCollection('signatures')
            ->acceptsMimeTypes(['image/jpg', 'image/jpeg', 'image/png', 'image/webp'])
            ->useDisk(config('filesystems.signatures'));
    }

    public function registerMediaConversions(?MediaLibraryMedia $media = null): void
    {
        $this->addMediaConversion('thumb')
            ->width(100)
            ->height(100)
            ->performOnCollections('avatar')
            ->nonQueued();

        $this->addMediaConversion('large')
            ->width(400)
            ->height(400)
            ->performOnCollections('avatar')
            ->nonQueued();
    }

Note I am updating signatures, not avatar, and yet there is an error for "thumb", which isn't defined as a conversion on the signatures collection, so I'm not sure why it's trying to look it up?!

Other things that might be important

    /*
     * Moves media on updating to keep path consistent. Enable it only with a custom
     * PathGenerator that uses, for example, the media UUID.
     */
    'moves_media_on_update' => true,
    /*
     * The class that contains the strategy for determining a media file's path.
     */
    //'path_generator' => Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator::class,
    'path_generator' => \App\Services\MediaLibrary\UuidPathGenerator::class,
namespace App\Services\MediaLibrary;

use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator;

class UuidPathGenerator extends DefaultPathGenerator
{
    /**
     * Get a unique base path for the given media.
     */
    protected function getBasePath(Media $media): string
    {
        $prefix = config('media-library.prefix', '');

        if ($prefix !== '') {
            return $prefix.'/'.$media->getAttribute('uuid');
        }

        return $media->getAttribute('uuid');
    }
}

media-library.prefix = '' so the above just returns uuid for the path, giving paths like "signature_url": "/storage/cf244a39-fa52-42e5-a5e0-62a9ffa5564b/33275f9e-b3a4-44a6-9334-2384f9b6eeaf.jpg"

More information, the media being added is added from base64 so it has a .tmp extension, that is then changed to the correct extension detected by the mime-type (something that media-lib doesn't do automatically! - see the graveyard that is - #3089), this causes the Observer to trigger and run, which is when the problems occurs, within syncFileNames() inside Spatie\MediaLibrary\MediaCollections\Models\Observers\MediaObserver.

Something is causing backwards breaking in 11.10

@SlyDave
Copy link
Contributor Author

SlyDave commented Nov 14, 2024

The following pull added to 11.10 causes the issue: #3715

Reverting:

        $conversion = $this
            ->getConversions($this->media->collection_name)
            ->first(fn (Conversion $conversion) => $conversion->getName() === $name);

back to

        $conversion = $this->first(fn (Conversion $conversion) => $conversion->getName() === $name);

fixes the crash

@srustamov
Copy link

same issue

@SlyDave
Copy link
Contributor Author

SlyDave commented Nov 14, 2024

ok, so the new code does what is expected and returns null for conversion when, looking for conversions on a collection that doesn't have conversions.

The problem is this is what is throwing the exception

        if (! $conversion) {
            throw InvalidConversion::unknownName($name);
        }

The question then becomes why is ConversionCollection::getByName() being called for a collection that doesn't have conversions

which brings you toFilesystem->renameConversionFiles() -> foreach ($media->getMediaConversionNames()... which comes from Filesystem->syncFileNames which comes from the aforementioned MediaObserver->updating()

If we follow that, we can see that all the code calls $media->getMediaConversionNames() and loops over them, it doesn't filter this list down by the conversions actually available for the currently observed collection - so it's running renameConverionsFiles on all conversions configured for the media, not just the ones for the collection - and thus when it hits the getByName which now returns null, it crashes.

// $media->getMediaConversionNames() returns all media conversions (regardless of collection)
// $conversionCollection only contains conversions for the collection the media is for
// thus a call to getByName() on each of the media is going to return null if a media has multiple collections but not all collections have all conversions defined

        $conversionCollection = ConversionCollection::createForMedia($media);

        foreach ($media->getMediaConversionNames() as $conversionName) {
            $conversion = $conversionCollection->getByName($conversionName); <--- crash

I think the woopies here is thinking that $conversionCollection means conversions for a Media Collection, and not a collection of Conversions for the Media :D

@timvandijck
Copy link
Member

Thanks for the investigation @SlyDave . I believe the best thing is to just revert the PR for now to avoid further problems.

Maybe @StyxUA who created the PR can chime in on this too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants