Fixing the ‘wysiwyg is not under storage root path’ error in Magento 2

If the media directory within your Magento 2 application is being used as a symlink, then there is a chance you may have encountered an issue with uploading media images in the admin. The error in question is as follows: /your/symlinked/mediadir/wysiwyg is not under storage root path. This post will describe steps to take in order to go about fixing the ‘wysiwyg is not under storage root path’ error in Magento 2.

Firstly, it should be known that this issue is currently reproducible in Magento Open Source version 2.2.3, however it may also exist in other Magento versions.

The issue can be pinpointed within the Magento\Framework\App\Filesystem\DirectoryResolver class within the validatePath() method.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Framework\App\Filesystem;

/**
 * Magento directories resolver.
 */
class DirectoryResolver
{
    /**
     * @var DirectoryList
     */
    private $directoryList;

    /**
     * @param DirectoryList $directoryList
     */
    public function __construct(DirectoryList $directoryList)
    {
        $this->directoryList = $directoryList;
    }

    /**
     * Validate path.
     *
     * Gets real path for directory provided in parameters and compares it with specified root directory.
     * Will return TRUE if real path of provided value contains root directory path and FALSE if not.
     * Throws the \Magento\Framework\Exception\FileSystemException in case when directory path is absent
     * in Directories configuration.
     *
     * @param string $path
     * @param string $directoryConfig
     * @return bool
     * @throws \Magento\Framework\Exception\FileSystemException
     */
    public function validatePath($path, $directoryConfig = DirectoryList::MEDIA)
    {
        $realPath = realpath($path);
        $root = $this->directoryList->getPath($directoryConfig);
        
        return strpos($realPath, $root) === 0;
    }
}

In order to resolve the issue with a symlinked media directory, $root must also be passed through the realPath() method.

Therefore there are a couple of ways to resolve the issue. The first method is to override the method using a preference.

This can be done within a custom module, first by adding the following contents within the module’s di.xml file.

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Framework\App\Filesystem\DirectoryResolver"
                type="[Vendor]\[Module]\App\Filesystem\DirectoryResolver"/>
</config>

Then adding the class, with the overriding validatePath() method.

<?php
namespace [Vendor]\[Module]\App\Filesystem;

use Magento\Framework\App\Filesystem\DirectoryList;

/**
 * Magento directories resolver.
 */
class DirectoryResolver
{
    /**
     * @var DirectoryList
     */
    private $directoryList;

    /**
     * @param DirectoryList $directoryList
     */
    public function __construct(DirectoryList $directoryList)
    {
        $this->directoryList = $directoryList;
    }

    /**
     * Validate path.
     *
     * Gets real path for directory provided in parameters and compares it with specified root directory.
     * Will return TRUE if real path of provided value contains root directory path and FALSE if not.
     * Throws the \Magento\Framework\Exception\FileSystemException in case when directory path is absent
     * in Directories configuration.
     *
     * @param string $path
     * @param string $directoryConfig
     * @return bool
     * @throws \Magento\Framework\Exception\FileSystemException
     */
    public function validatePath($path, $directoryConfig = DirectoryList::MEDIA)
    {
        $realPath = realpath($path);
        $root = realpath($this->directoryList->getPath($directoryConfig));

        return strpos($realPath, $root) === 0;
    }
}

The second method is to add a patch file using the Composer patches package.

If you’ve viewed previous articles involving Applying Magento 2 Github Patches, you can install a patch file that will patch the issue after the magento/framework composer package has been added.

The patch can be seen below.

--- vendor/magento/framework/App/Filesystem/DirectoryResolver.php
+++ vendor/magento/framework/App/Filesystem/DirectoryResolver.php
@@ -42,7 +42,7 @@
     public function validatePath($path, $directoryConfig = DirectoryList::MEDIA)
     {
         $realPath = realpath($path);
-        $root = $this->directoryList->getPath($directoryConfig);
+        $root = realpath($this->directoryList->getPath($directoryConfig));

         return strpos($realPath, $root) === 0;
     }