Undefined property Cms\Components\ViewBag::assetUrlPath

Hi there,

I just updated my October website from v3.7 to v4.0 and followed the upgrade guide, but I get the following error when viewing the front-end website or settings pages in the backend (SettingsModel):

Call to undefined property Cms\Components\ViewBag::assetUrlPath
~/vendor/october/rain/src/Extension/ExtendableTrait.php line 457

I have tried removing PHP files from the storage/framework folder and cleared cache. I also wanted to run the ‘php artisan october:optimize’ command, but this too returns the same error.

I use a local environment with Laravel Herd and using php 8.3.

Does anybody have an idea how to fix this?

Thanks!

Hey @kevin-invato

The error at ExtendableTrait.php line 457 suggests the Extendable system is trying to access assetUrlPath as a dynamic property, but we need to know what is calling it. The stack trace would reveal if it’s:

  • Twig template code (e.g., {{ viewBag.assetUrlPath }})
  • A plugin accessing ViewBag properties
  • Internal CMS rendering logic
  • Something else entirely

I used Augment (AI) to analyse the stracktrace and this is the response. Weird thing about the settingsmodel pages is that when there is a pagefinder fieldtype, it breaks. If I remove the pagefinder field the page works, but I get a lot of richeditor errors in the console.

Analysis of the Stacktrace

The Problem

The error occurs when October CMS tries to initialize a ViewBag component:

Error location:

The Error Flow

  1. Trigger (#32-#19): A PageFinder formwidget in the backend tries to resolve a page (ketels/cv-ketel)
  2. Page Loading (#19-#6): October CMS loads the page and triggers the afterFetch() event
  3. ViewBag Initialization (#3-#2):
  • CmsCompoundObject->getViewBag() is called
  • This creates a new ViewBag component via ComponentBase->__construct()
  1. Property Assignment (#1):
  • In

ComponentBase.php

line 107, $this->assetUrlPath = $this->getComponentAssetUrlPath() is executed

  • This calls Extendable->__set('assetUrlPath', '/modules/cms')
  1. The Error (#0):
  • ExtendableTrait->extendableSet() fails because ViewBag has no assetUrlPath property and doesn’t define a __set() method

Why Does This Fail?

In

ViewBag.php

:

  • :white_check_mark: Has a __get() method that returns null for unknown properties
  • :x: Has no __set() method
  • :x: Has a __isset() method that returns false for unknown properties

The Problem: When ComponentBase->__construct() tries to set $this->assetUrlPath:

  1. PHP calls __set() because the property doesn’t exist
  2. ViewBag has no own __set(), so it goes to the parent (Extendable)
  3. Extendable->__set() calls extendableSet()
  4. extendableSet() checks if the property exists via property_exists() or __isset()
  5. ViewBag->__isset('assetUrlPath') returns false
  6. BOOM - Exception: “Call to undefined property”

Why Did This Work in v3.x?

In October CMS v3.x, the ExtendableTrait was probably less strict, or ViewBag had a different implementation that allowed this.

The Solution

There are 3 possible solutions:

Option 1: Fix in ViewBag (what I did earlier)

  • Add __set() method that delegates to parent::__set()
  • Modify __get() and __isset() to fall back to parent

Option 2: Fix in ComponentBase

  • Check if the component is a ViewBag and skip setting assetUrlPath
  • Not ideal, but would work

Option 3: Report as bug to October CMS

  • This is clearly a regression in v4.0
  • The ViewBag component should work like other components

Conclusion

This is a bug in October CMS v4.0. The ViewBag component has incomplete magic methods that are not compatible with how ComponentBase tries to set properties. The fix I implemented earlier (option 1) is the correct solution, but should actually be implemented by the October CMS team.

PS: the first item in the errorflow is referring to ketels/cv-ketel, but it’s different for all settingsmodel. Its the value of the pagefinder data.

1 Like

Hi @kevin-invato

Thanks for this report. Something here doesn’t add up, could you check your codebase to ensure that this property exists here: october/modules/system/traits/AssetMaker.php at 4.x · octobercms/october · GitHub

As we see, the property is defined and is public:

/**
 * @var string assetUrlPath specifies the public path to the asset directory.
 */
public $assetUrlPath;

This means the error doesn’t quite make sense in the current codebase, and this analysis doesn’t appear to identify the issue.

Hi @daftspunk

That url ’ https://github.com/octobercms/october-private/blob/4.x/modules/system/traits/AssetMaker.php#L39 ’ is a dead end- 404. But i found it in my codebase :wink: .

Below you will find my findings. Be aware, we use AI and i have used AI (Claude Code) to help me find this issue and propose a solution. I hope this gives you more insight into getting this resolved.

Issue: Dynamic Property Error After Upgrading from October CMS v3 to v4

Problem Description

After upgrading from October CMS v3 to v4 (Laravel 12, PHP 8.3), we encounter the following error:

BadMethodCallException: Call to undefined property Cms\Components\ViewBag::assetUrlPath
at vendor/october/rain/src/Extension/ExtendableTrait.php line 507

This error occurs in the ComponentBase::__construct() method when trying to set assetPath and assetUrlPath
properties (lines 106-107).

Root Cause

  1. PHP 8.2+ Restriction: PHP 8.2+ no longer allows dynamic properties by default unless a class has the
    #[AllowDynamicProperties] attribute.

  2. ExtendableTrait Behavior: The ExtendableTrait::__set() method (line 507) throws a BadMethodCallException when
    trying to set a property that:

    • Is not declared as a public property on the class
    • Is not registered as a dynamic property via extendableAddDynamicProperty()
    • Does not exist in the parent class chain
  3. AssetMaker Trait Properties: The assetPath and assetUrlPath properties are declared in the
    System\Traits\AssetMaker trait (lines 34 and 39), but the ExtendableTrait::__set() method’s property_exists()
    check (line 477) does not properly recognize trait properties in PHP 8.2+, causing the exception to be thrown.

  4. ViewBag Instantiation: When ViewBag is instantiated without a controller context in
    CmsCompoundObject::getViewBag() (line 366) using new ViewBag(null, []), the ComponentBase constructor still
    attempts to set these properties, triggering the error.

Current Workaround

We’ve had to explicitly declare assetPath and assetUrlPath as public properties in the ComponentBase class:

abstract class ComponentBase extends Extendable implements CallsAnyMethod
{
    use \System\Traits\AssetMaker;
    // ... other traits and properties ...

    /**
     * @var string assetPath specifies the relative path to the asset directory.
     * Fix for October CMS v4 with PHP 8.2+ - explicitly declare to avoid ExtendableTrait issues
     */
    public $assetPath;

    /**
     * @var string assetUrlPath specifies the public path to the asset directory.
     * Fix for October CMS v4 with PHP 8.2+ - explicitly declare to avoid ExtendableTrait issues
     */
    public $assetUrlPath;

    // ... rest of class ...
}

We also had to add a null check in ComponentBase::__call() (line 374):

// Fix for October CMS v4 - check if controller exists before calling method_exists
if ($this->controller && method_exists($this->controller, $method)) {
    return call_user_func_array([$this->controller, $method], $parameters);
}

Impact

This issue affects all components that extend ComponentBase, particularly when they are instantiated without a controller context (like ViewBag in CmsCompoundObject::getViewBag()).

Environment

  • October CMS v4
  • Laravel 12
  • PHP 8.3+

Thanks @gldrenthe89

Unfortunately I couldn’t reproduce the issue. Could you provide some replication instructions to help me arrive at the error? Then I can confirm that the fix is appropriate.

So far it doesn’t make sense why it works for me and not for you.

Even your Current Workaround doesn’t make sense because it implements a trait that contains those exact properties.

You should see it in your codebase ^^ please compare it with this file: october/modules/system/traits/AssetMaker.php at 4.x · octobercms/october · GitHub

Hopefully this helps.

The issue occurs whenever a plugin (or custom code) uses a pagefinder form field.
We’re seeing this not only in our own plugins but also in well-known ones like the OFFLINE Boxes plugin (which also uses the pagefinder field on its boxes).

The error is thrown in vendor code, specifically inside the extendableSet() method (around line 428 in ExtendableTrait.php):

// Undefined property, throw an exception to catch it
if (!$found) {
    throw new BadMethodCallException(sprintf(
        'Call to undefined property %s::%s',
        static::class,
        $name
    ));
}

This check fails to detect the dynamic properties provided by the AssetMaker trait (which ComponentBase, and therefore ViewBag, uses). As a result, it incorrectly reports that assetUrlPath does not exist.

Key points:

  • The problem is not caused by anything in our own code, we’ve thoroughly checked and even ran extensive analysis with Claude.
  • If the pagefinder field is removed, the page loads perfectly.
  • The moment a pagefinder field is present → the vendor crash occurs.

The only reliable fix we’ve found so far is the workaround mentioned earlier in this thread (explicitly declaring the properties in ComponentBase and/or adding a null-check in __call()).

Hopefully this can be properly addressed in a future October CMS update so that ViewBag + AssetMaker works correctly with dynamic properties again.

Has anyone else run into this issue?

For reference, here’s the error screenshot of the error again:

Thanks in advance!

Hi @gldrenthe89

Thanks for the extra detail.

Right now I still can’t line this up with a stock v4 install.

assetUrlPath is a real, public property in the System\Traits\AssetMaker trait.

So if ExtendableTrait->__set() can’t see it, something else is going on in your app:

  • a partial / mixed vendor upgrade (old october/rain with new core, or vice versa)
  • a class override / alias (custom ViewBag or ComponentBase)
  • a plugin loading an old class copy
  • cached opcache artifacts pointing at old files
  • an old backend skin

To move this forward, I need a deterministic repro that starts from a clean base.

What I need from you

1. Confirm it happens on a clean install

  • New October v4 project
  • No custom code changes
  • Then install one plugin that uses PageFinder (OFFLINE.Boxes is perfect)

If it fails there, list the exact steps:

  • which plugin version
  • which model
  • the exact fields.yaml snippet with the PageFinder
  • what page you open in the backend to trigger it

2. Provide the real stack trace (not the AI summary)

  • full stack trace text from the exception page
  • the first frame that enters your plugin code (if any)
  • the vendor/october/* file paths shown in the trace

3. Quick isolation checks in your current project

  • Disable all plugins except the one with PageFinder

  • Switch to the default backend theme / skin

  • Restart PHP (important if you use opcache), then run:

    • php artisan cache:clear
    • php artisan config:clear
    • php artisan view:clear

One question that will narrow this fast

If you run this in php artisan tinker:

property_exists(\Cms\Components\ViewBag::class, 'assetUrlPath');

What does it return on your machine?

If you give me the outputs + a clean-install repro path, I can either reproduce it and patch it, or point to the actual mismatch causing it.

First i have the tinker output:

image

I need time to set-up a fresh project. When i have done all steps as mentioned above i will give all the results.

1: I have created a new v4 project, installed is as shown in the docs. Running it on php 8.3 using laravel Herd (latest). I have installed the OFFLINE Boxes, created a ‘test’ box with the Pagefinder in it. When loading the page. it loads. But adding the box, then trying to use the pagefinder field there is a console error thrown:

2: Stack trace + a screenshot below the full stack trace:
We’re sorry, but an unhandled error occurred. Please see the details below.

Call to undefined property Cms\Components\ViewBag::assetUrlPath

~/vendor/october/rain/src/Extension/ExtendableTrait.php line 457

  • Type

Undefined

  • Exception

BadMethodCallException

451

452

453

454

455

456

457

458

459

460

461

462

463 parent::__set($name, $value);

$found = true;

}

// Undefined property, throw an exception to catch it

if (!$found) {

throw new BadMethodCallException(sprintf(

'Call to undefined property %s::%s',

static::class,

$name

));

}

}

Stack Trace

# Called Code Document Line
80 October\Rain\Extension\Extendable->extendableSet(…) ~/vendor/october/rain/src/Extension/Extendable.php 47
79 October\Rain\Extension\Extendable->__set(…) ~/modules/cms/classes/ComponentBase.php 107
78 Cms\Classes\ComponentBase->__construct(…) ~/modules/cms/classes/CmsCompoundObject.php 366
77 Cms\Classes\CmsCompoundObject->getViewBag() ~/modules/cms/classes/CmsCompoundObject.php 382
76 Cms\Classes\CmsCompoundObject->fillViewBagArray() ~/modules/cms/classes/CmsCompoundObject.php 147
75 Cms\Classes\CmsCompoundObject->parseSettings() ~/modules/cms/classes/CmsCompoundObject.php 91
74 Cms\Classes\CmsCompoundObject->afterFetch() ~/vendor/october/rain/src/Halcyon/Concerns/HasEvents.php 53
73 October\Rain\Halcyon\Model->October\Rain\Halcyon\Concerns{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php 488
72 Illuminate\Events\Dispatcher->Illuminate\Events{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php 315
71 Illuminate\Events\Dispatcher->invokeListeners(…) ~/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php 295
70 Illuminate\Events\Dispatcher->dispatch(…) ~/vendor/october/rain/src/Halcyon/Concerns/HasEvents.php 207
69 October\Rain\Halcyon\Model->fireModelEvent(…) ~/vendor/october/rain/src/Halcyon/Model.php 463
68 October\Rain\Halcyon\Model->newFromBuilder(…) ~/vendor/october/rain/src/Halcyon/Model.php 481
67 October\Rain\Halcyon\Model::October\Rain\Halcyon{closure}(…)
66 array_map(…) ~/vendor/october/rain/src/Halcyon/Model.php 480
65 October\Rain\Halcyon\Model::hydrate(…) ~/vendor/october/rain/src/Halcyon/Builder.php 415
64 October\Rain\Halcyon\Builder->getModels(…) ~/vendor/october/rain/src/Halcyon/Builder.php 213
63 October\Rain\Halcyon\Builder->get()
62 call_user_func_array(…) ~/vendor/october/rain/src/Halcyon/Model.php 1375
61 October\Rain\Halcyon\Model->__call(…) ~/modules/cms/classes/CmsCompoundObject.php 495
60 Cms\Classes\CmsCompoundObject->__call(…) ~/modules/cms/classes/CmsObject.php 132
59 Cms\Classes\CmsObject::listInTheme(…) ~/modules/cms/classes/Page.php 95
58 Cms\Classes\Page->getLayoutOptions() ~/plugins/offline/boxes/models/Page.php 406
57 OFFLINE\Boxes\Models\Page->getLayoutOptions() ~/plugins/offline/boxes/formwidgets/BoxesEditor.php 776
56 OFFLINE\Boxes\FormWidgets\BoxesEditor->resolvePageModel() ~/plugins/offline/boxes/formwidgets/BoxesEditor.php 673
55 OFFLINE\Boxes\FormWidgets\BoxesEditor->buildState() ~/plugins/offline/boxes/formwidgets/BoxesEditor.php 126
54 OFFLINE\Boxes\FormWidgets\BoxesEditor->prepareVars() ~/plugins/offline/boxes/formwidgets/BoxesEditor.php 113
53 OFFLINE\Boxes\FormWidgets\BoxesEditor->render() ~/plugins/offline/boxes/controllers/editorcontroller/index.php 1
52 include(…) ~/modules/system/traits/ViewMaker.php 272
51 OFFLINE\Boxes\Controllers\EditorController->makeFileContents(…) ~/modules/system/traits/ViewMaker.php 117
50 OFFLINE\Boxes\Controllers\EditorController->makeView(…) ~/modules/backend/classes/Controller.php 406
49 Backend\Classes\Controller->execPageAction(…) ~/modules/backend/classes/Controller.php 274
48 Backend\Classes\Controller->run(…) ~/modules/backend/classes/BackendController.php 143
47 Backend\Classes\BackendController->run(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Controller.php 54
46 Illuminate\Routing\Controller->callAction(…) ~/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php 43
45 Illuminate\Routing\ControllerDispatcher->dispatch(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Route.php 265
44 Illuminate\Routing\Route->runController() ~/vendor/laravel/framework/src/Illuminate/Routing/Route.php 211
43 Illuminate\Routing\Route->run() ~/vendor/laravel/framework/src/Illuminate/Routing/Router.php 822
42 Illuminate\Routing\Router->Illuminate\Routing{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 180
41 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php 50
40 Illuminate\Routing\Middleware\SubstituteBindings->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
39 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php 48
38 Illuminate\View\Middleware\ShareErrorsFromSession->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
37 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php 120
36 Illuminate\Session\Middleware\StartSession->handleStatefulRequest(…) ~/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php 63
35 Illuminate\Session\Middleware\StartSession->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
34 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php 36
33 Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
32 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php 74
31 Illuminate\Cookie\Middleware\EncryptCookies->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
30 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 137
29 Illuminate\Pipeline\Pipeline->then(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Router.php 821
28 Illuminate\Routing\Router->runRouteWithinStack(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Router.php 800
27 Illuminate\Routing\Router->runRoute(…) ~/vendor/laravel/framework/src/Illuminate/Routing/Router.php 764
26 Illuminate\Routing\Router->dispatchToRoute(…) ~/vendor/october/rain/src/Router/CoreRouter.php 32
25 October\Rain\Router\CoreRouter->dispatch(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php 200
24 Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 180
23 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/plugins/invato/settings/classes/BackendRedirectMiddleware.php 32
22 Invato\Settings\Classes\BackendRedirectMiddleware->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
21 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php 109
20 Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(…) ~/vendor/october/rain/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php 23
19 October\Rain\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
18 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php 21
17 Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php 51
16 Illuminate\Foundation\Http\Middleware\TrimStrings->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
15 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php 27
14 Illuminate\Http\Middleware\ValidatePostSize->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
13 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php 48
12 Illuminate\Http\Middleware\HandleCors->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
11 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php 58
10 Illuminate\Http\Middleware\TrustProxies->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
9 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php 22
8 Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
7 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php 26
6 Illuminate\Http\Middleware\ValidatePathEncoding->handle(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 219
5 Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(…) ~/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php 137
4 Illuminate\Pipeline\Pipeline->then(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php 175
3 Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php 144
2 Illuminate\Foundation\Http\Kernel->handle(…) ~/index.php 42
1 require(…) ~ 167

3: Disabled all plugins. ran the command. also try to run php artisan october:optimize. throws the same error:
image

To be complete in my post. Also the tinker command result again:
image

Doing the same thing,

Fresh install
Install OFFLINE.Boxes
Tinker

I get a different result:

λ php artisan tinker
Psy Shell v0.12.18 (PHP 8.4.2 — cli) by Justin Hileman
New PHP manual is available (latest: 3.0.0). Update with `doc --update-manual`
> property_exists(\Cms\Components\ViewBag::class, 'assetUrlPath');
= true

How can this be? (Please don’t answer with AI)

I am sorry. the tinker response was done in the repo with the issue. In the test repo it gives a true back… This is very weird as ViewBag is a ‘vendor’ file, one that is being pushed to codebase on upgrades. I have copied the CMS directory from the test repo to the repo with the issue to check if october:update missed something. No changes and same ‘false’ return. below the tinker response fromt the test repo.

image

That’s OK. It’s progress…

Now we need to determine why it returns false for your other installation. There can be many reasons, however, only the code will reveal why.

The next step is an isolation test. Add plugins/code to the fresh installation until it reads false again, then you will know what element/object causes it. Then, continue the investigation down that path.

Some ideas: I have seen plugins short-circuit this class using the autoloader. Loading their own version of AssetMaker, ViewMaker, etc., before the official October one, and this would cause the symptoms.

I hope this helps!

I believe we’ve identified the root cause of the issue.

It appears to be caused by the following plugin: Backend Skin by Cydrick Nonog

Due to the way this plugin overrides the AssetMaker trait, it was quite difficult to trace. We were using this plugin to apply our own custom backend theme.

Going forward, we will implement our backend styling in a different (and cleaner) way and will stop using this plugin. Looking at the GitHub repository, it seems development has been stalled for quite some time.

Thank you very much for thinking along with us and for your support!

If you have any recommendations or know of a more official / recommended way to implement a custom backend theme in October CMS, we would greatly appreciate your guidance.

Thanks again for your help!

Hi @gldrenthe89,

To create your own skin:

  1. In config/backend.php, register your backend skin path, for example:

    'skin' => 'Author\Plugin\Classes\BackendSkin',
    
  2. Then, in your backend skin class (e.g. BackendSkin.php), define where the overridden views should be loaded from:

    <?php namespace Author\Plugin\Classes;
    
    use Backend\Skins\Standard;
    
    /**
     * Modified backend skin information file.
     *
     * This adds an additional path to override the default backend layouts.
     */
    class BackendSkin extends Standard
    {
        /**
         * {@inheritDoc}
         */
        public function getLayoutPaths()
        {
            return [
                base_path() . '/plugins/author/plugin/skin/layouts',
                $this->skinPath . '/layouts'
            ];
        }
    }
    

After that, you can copy any file from the original backend location (for example,
modules/backend/layouts/_mainmenu.php) into
/plugins/author/plugin/skin/layouts and override it there.

1 Like