Skip to content

LESS/CSS error after upgrade to 2.4.4-p2

I am in the process of upgrading from 2.4.2 to 2.4.4-p2. I ran all the update commands and then switched to php 8.1 and now have a site which appears and mostly works but the CSS isn’t working. I have tried running setup:static-content:deploy -f, clearing cache, reindexing etc etc but no joy.

I’m not sure if this is related but I’m only seeing the luma logo rather than the main site logo – static/version1669984777/frontend/Website/luma_childtheme/en_GB/images/logo.svg

Error at static/version1669984777/frontend/Website/luma_childtheme/en_GB/css/styles-m.css as follows:

Unable to get content for 'frontend/Owlbarn/luma_child/en_GB/css/source/_extend-child.less'
<pre>#1 MagentoFrameworkViewAssetPreProcessorAlternativeSource->processContent() called at [vendor/magento/framework/View/Asset/PreProcessor/AlternativeSource.php:114]
#2 MagentoFrameworkViewAssetPreProcessorAlternativeSource->process() called at [vendor/magento/module-developer/Model/View/Asset/PreProcessor/PreprocessorStrategy.php:78]

Line 114 is this line:

$chain->setContent($this->processContent($path, $content, $module, $context));

vendor/magento/framework/View/Asset/PreProcessor/AlternativeSource.php Full file as follows:

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

use MagentoFrameworkObjectManagerInterface;
use MagentoFrameworkViewAssetContentProcessorInterface;
use MagentoFrameworkViewAssetFileFallbackContext;
use MagentoFrameworkViewAssetLockerProcessInterface;
use MagentoFrameworkViewAssetPreProcessorAlternativeSourceAssetBuilder;

/**
 * Class AlternativeSource
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class AlternativeSource implements AlternativeSourceInterface
{
    /**
     * The key name of the processor class
     */
    const PROCESSOR_CLASS = 'class';

    /**
     * @var HelperSortInterface
     */
    private $sorter;

    /**
     * @var array
     */
    private $alternatives;

    /**
     * @var ObjectManagerInterface
     */
    private $objectManager;

    /**
     * @var array
     */
    private $alternativesSorted;

    /**
     * @var LockerProcessInterface
     */
    private $lockerProcess;

    /**
     * @var string
     */
    private $lockName;

    /**
     * @var AssetBuilder
     */
    private $assetBuilder;

    /**
     * @var FilenameResolverInterface
     */
    private $filenameResolver;

    /**
     * Constructor
     *
     * @param FilenameResolverInterface $filenameResolver
     * @param ObjectManagerInterface $objectManager
     * @param LockerProcessInterface $lockerProcess
     * @param HelperSortInterface $sorter
     * @param AssetBuilder $assetBuilder
     * @param string $lockName
     * @param array $alternatives
     */
    public function __construct(
        FilenameResolverInterface $filenameResolver,
        ObjectManagerInterface $objectManager,
        LockerProcessInterface $lockerProcess,
        HelperSortInterface $sorter,
        AssetBuilder $assetBuilder,
        $lockName,
        array $alternatives = []
    ) {
        $this->objectManager = $objectManager;
        $this->lockerProcess = $lockerProcess;
        $this->sorter = $sorter;
        $this->alternatives = $alternatives;
        $this->lockName = $lockName;
        $this->assetBuilder = $assetBuilder;
        $this->filenameResolver = $filenameResolver;
    }

    /**
     * @inheritdoc
     * @throws UnexpectedValueException
     */
    public function process(Chain $chain)
    {
        $path = $chain->getAsset()->getFilePath();
        $content = $chain->getContent();
        if (trim($content) !== '') {
            return;
        }

        try {
            $this->lockerProcess->lockProcess($this->lockName);

            $module = $chain->getAsset()->getModule();

            /** @var FallbackContext $context */
            $context = $chain->getAsset()->getContext();
            $chain->setContent($this->processContent($path, $content, $module, $context));
        } finally {
            $this->lockerProcess->unlockProcess();
        }
    }

    /**
     * Preparation of content for the destination file
     *
     * @param string $path
     * @param string $content
     * @param string $module
     * @param FallbackContext $context
     * @return string
     * @throws UnexpectedValueException
     */
    private function processContent($path, $content, $module, FallbackContext $context)
    {
        if ($this->alternativesSorted === null) {
            $this->alternativesSorted = $this->sorter->sort($this->alternatives);
        }

        $path = $this->filenameResolver->resolve($path);
        foreach ($this->alternativesSorted as $name => $alternative) {
            $asset = $this->assetBuilder->setArea($context->getAreaCode())
                ->setTheme($context->getThemePath())
                ->setLocale($context->getLocale())
                ->setModule($module)
                ->setPath(
                    preg_replace(
                        '#.' . preg_quote(pathinfo($path, PATHINFO_EXTENSION)) . '$#',
                        '.' . $name,
                        $path
                    )
                )->build();

            $processor = $this->objectManager->get($alternative[self::PROCESSOR_CLASS]);
            if (!$processor  instanceof ContentProcessorInterface) {
                throw new UnexpectedValueException(
                    '"' . $alternative[self::PROCESSOR_CLASS] . '" has to implement the ContentProcessorInterface.'
                );
            }
            $content = $processor->processContent($asset);

            if (trim($content) !== '') {
                return $content;
            }
        }

        return $content;
    }

    /**
     * @inheritdoc
     */
    public function getAlternativesExtensionsNames()
    {
        return array_keys($this->alternatives);
    }

    /**
     * Check if file extension supported
     *
     * @param string $ext
     * @return bool
     */
    public function isExtensionSupported($ext)
    {
        return isset($this->alternatives[$ext]);
    }
}

Thanks for any help

ETA, I noticed that the commandline had errors as so:

Compilation from source: /home/website/public_html/vendor/magento/theme-frontend-blank/web/css/styles-l.less
Unable to get content for 'frontend/Website/luma_childtheme/en_GB/css/source/_extend-child.less'

The less files in vendor/magento did not have the underscore before them so I renamed styles-l and styles-m.less to _styles-l etc. Now I have no error on the commandline but still no CSS.
Error at styles-m.css now says:

Compilation from source: LESS file is empty: frontend/Website/luma_childtheme/en_GB/css/styles-m.less
<pre>#1 MagentoFrameworkViewAssetPreProcessorAlternativeSource->processContent() called at [vendor/magento/framework/View/Asset/PreProcessor/AlternativeSource.php:114]