Overview
Canvas creates a content dependency on SDCs. Because SDCs are generally being provided by themes (especially Mercury and Byte), this makes it impossible to uninstall a theme without breaking all of your canvas-enabled content.
It's also not currently possibly to change the default theme without a fatal error due to #3549814: Component tree containing theme's SDCs triggers errors when the theme is not the default anymore although the fatal can be worked around with the fallback component logic. The content would still be broken though.
#3550019: Add ThemeUninstallValidatorInterface similar to ModuleUninstallValidatorInterface is open against core to prevent theme uninstallation, but that won't allow you to change your theme, only prevent the content breakage situation by locking you into your current theme.
This has been discussed in slack at least three times but I was unable to find an issue either against Canvas or Drupal core.
https://drupal.slack.com/archives/C072BF486FN/p1743537967924799?thread_t...
https://drupal.slack.com/archives/C072JMEPUS1/p1764606236102519?thread_t...
And most recently:
https://drupal.slack.com/archives/C072JMEPUS1/p1768422063724699
Proposed resolution
This might need a new API in core, but I'm not sure what that is, and Canvas would be the main consumer, so opening this first - a core issue could follow.
#3546209: Support `replaces`: 2 SDCs with one replacing the other — Canvas creates `Component`s for both provides something not dissimilar to what might be needed - a way to say X SDC replaces Y SDC, but that API is only available to themes and it looks like potentially both themes might need to be installed at the same time, no 'just in time' swap for non-existing SDCs.
User interface changes
| Comment | File | Size | Author |
|---|---|---|---|
| #13 | workaround.png | 100.11 KB | f0ns |
| #11 | component-names-wiped-out.png | 48.13 KB | phenaproxima |
| #9 | look-ma-no-duplicates.png | 44.21 KB | phenaproxima |
| #9 | byte-fork-missing-header-and-footer.png | 484.04 KB | phenaproxima |
| #9 | byte-fork-and-byte-theme-both-installed.png | 272.26 KB | phenaproxima |
Comments
Comment #2
wim leersThanks for doing this write-up!
Indeed. That is why Canvas'
Componentconfig entities exist: to be able to reuse Drupal's config dependency checking (in tandem with thorough validation that e.g. verifies the SDC plugin referenced by such a config entity still exists).Any Canvas component tree (whether in a content entity such as a
\Drupal\canvas\Entity\Pageor in a config entity such as page region, content template …) references those Component config entities, and if it references a non-existing one, then that component tree won't pass validation.Because if it won't pass validation, then the component instance using that SDC (or whatever kind of component!) would fail to render, which means the component tree would be broken.
IOW: this is all intentional, to ensure data integrity.
Quoting
docs/config-management.md:Any usages of any Component config entity would prevent this uninstallation (see
\Drupal\canvas\Audit\ComponentAudit0👉 In today's Canvas, to be able to uninstall a theme whose SDCs are used in >=1 Canvas component tree, you'd need to update every single component tree that uses it, to stop using it. And for content entities, you'd have to delete past revisions that were using that component tree.
/admin/appearance/component/sdc.<provider>.<SDC name>/auditlists all places where it is used.(#3457504: XB field type: calculate all dependencies, store them, surface in new Component "Audit" operation introduced that route. See the screenshots in that issue summary.)
So:
To my knowledge, that just hasn't been a priority yet.
Comment #3
wim leersThat is definitely a bug — that should NOT happen. As long as the theme is still around, the SDCs are around, and no such bugs should occur.
IMHO that is the critical bug. Because switching to a new theme as the default but keeping the old one still installed would be sufficient to keep all existing component trees working, and would still offer the new theme's SDCs as the components to use in Canvas going forward.
Unless I'm missing something … what is reported here is basically "by design", as explained in my prior comment. And so, I would propose to reframe this issue:
(It'd be nice to do it generically instead of just for SDCs, and also to not require identical props. But that keeps the scope tight enough for it to be realistically achievable.)
Comment #4
wim leersRelated: #3463996: [META] When the field type, storage/instance settings, widget, expression or requiredness for an SDC/code component prop changes, the Content Creator must be able to upgrade.
Because … what if something like

replaceswere supported natively in Canvas' Component config entities? Then the UX that @lauriii proposed there, which he mocked like this (back in July 2024!!!):… could not only update the field type used underneath (to store the value, pass into the SDC prop, and generate an appropriate field widget), but also the SDC that is being used.
Comment #5
wim leersJust discovered that @effulgentsia extracted a piece of the issue linked above into a new issue: #3567413: When editing a Canvas entity with a component tree (e.g., page, template, or region), automatically upgrade component instance versions for cases where there's no impact on existing data.
Comment #6
catchI think there is quite a lot of info in this issue between the two of us, so not sure whether it really 'needs more info', it certainly needs more ideas on what the solution should be.
I don't really think that being able to change theme on a Drupal site is a 'feature request', that is basic functionality that people have been able to do in Drupal for 20 years without breaking their content, that is now not possible due to Canvas' data model and lack of options to mitigate it. It would have been less of an issue if component libraries were being centralised in modules instead of themes (which themes could then depend on), but there have been specific decisions not to do that in Mercury/Byte, alongside very strong discouragement of subthemes, so that content becomes coupled to a specific, named theme machine name, not even a specific implementation of a design system.
But maybe a task is more appropriate.
Comment #7
alexpottThis does feel like a bug though. If you:
=> Canvas page and templates are broken.
Comment #8
phenaproxima@alexpott, I'm a tad confused by your comment. Is this what's happening?
If that's causing a crash, then I would assume #3549814: Component tree containing theme's SDCs triggers errors when the theme is not the default anymore is at fault.
If it's not causing a crash, then what you mean by "broken"?
Comment #9
phenaproximaI discussed this with @alexpott. He said this happens for him:
So that's what I did. I hereby document my findings.
I started with Drupal CMS 2.x HEAD. Cleanly installed Byte:
ddev drush si -y ../recipes/byte. That worked fine. As with any clean install of Byte, byte_theme is the theme in use, and it looked good:Then I created a fork of Byte Theme, creatively called Byte Fork. I used these commands:
Then I edited byte_fork to rename certain files (e.g.
byte_theme.info.ymltobyte_fork.info.yml) and did a broad search-and-replace to changebyte_themetobyte_fork.You can see that Byte Fork was available to be installed on the Appearance page:
I clicked "Install and set as default". As expected:
Visiting the front page again, I saw this:
So that confirms @alexpott's experience that the page regions are gone. That makes sense; the page regions are tied to a specific theme, and Canvas doesn't do anything to port them from one theme to another. This is probably something Canvas needs to address in some way.
However, I didn't see anything like this:
The actual content looked fine. The editor UI in Canvas also worked fine; I could still see the list of components (with names!) and edit them. One interesting point is that I was not seeing duplicates of the available components (even after clearing the caches) even though I would kind of expect to:
Two themes, both alike in dignity, both installed and providing the same set of components under different machine names -- why don't I see a copy of every component?
But I still don't see what @alexpott is talking about with the content going weird and the components not having names. I therefore conclude that, although there is clearly buggy behavior here, this needs steps to reproduce.
Comment #10
catchI think I saw something about this in slack - could it be that the canvas editor only shows components for the current (default?) theme, and potentially base themes, but not for any other themes that are installed?
Comment #11
phenaproximaIn a Slack DM with me, @alexpott clarified this:
I confirmed that, if you do what I did in #9, the Layers tab of the Canvas UI does indeed wipe out the real component names, replacing all of them with "Component":
So that's a legitimate bug.
That said, @alexpott and I agree that:
drupal generate-theme) under a new machine name. This probably calls for some kind of just-in-time migration that Canvas implements, if it needs to map existing component instances to new ones 1:1. Scary stuff.ThemeInstallerInterfaceso as to provide this guardrail.Comment #12
f0ns commentedHappy I found this issue.
Feels like I'm running into the same problems as described above.
I have a Drupal installer which is recipe based. This also adds default content to the website and has a theme.
Now I'm looking into a way to generate themes easily based on that. Adding a
starterkit.ymlfile felt like the way to go so I've added that. I then generated a new theme and enabled it and everything broke.Problem 1: the placement of blocks (solved)
The first thing that I fixed was the block layout placement (/admin/structure/block). This config was in a recipe and I moved it to my theme.
After digging around I've learned I could create a StarterKit.php with a class that adds a postProcess(). In this function I get all the config files from the initial theme and I adjust them (change theme name, alter id, alter theme dependency).
When I now enable my generated theme the block layout is just as it was in the theme from which I generated the new one.
Problem 2: components and Drupal Canvas (
still looking for a solutionsolved)As I inject my installation with content there is a connection between this content and the SDC's in the original theme.
What would be the best way to fix this?
- Option A: add
replaces:to every component in the new theme automatically that references to the original one. This feels hacky to me?- Option B: find a way to also deal with this via postProcess()
Update:
I think I've solved this one by going for Option A & Option B combined haha. Every component in the new theme now automatically gets the
replaces:reference to the original component. I've added this in the postProcess() function of the StarterKit.php file.Problem 3: Drupal Canvas organisation (
still looking for a solutionsolved)My Drupal Canvas sidebar is quite organised (I only show my own SDC's and a lot of stuff is disabled to keep things clean). When generating a new theme I've noticed that all this configuration is ignored and the sidebar is filled with stuff that I didn't want to be there initially. Still need to look into that.
Update:
It appears this also got solved by solving Problem 2 with
replaces:. When I now generate and enable the new theme the Drupal Canvas sidebar appears to be empty. A cache clear all fixes this and everything appears to be organised as it was.All advice here is appreciated but I felt like the above had a connection with this issue so I wanted to share this here.
Thanks!
Update: Solved the three problems above and tried to document them in case anyone else encounters this.
I also uninstalled the initial theme and deleted it from the themes directory itself and cleared the cache. Everything appeared to be running smoothly but in the Canvas builder I now see:
So I need to figure that one out before I can disable and delete the initial theme.
Comment #13
f0ns commentedUpdate:
Not the ideal solution but I got this fixed.
I made some migration functionality with the following options:
It automatically points everything to the new theme, checks the component versions and updates where needed and also removes old references to avoid Drupal Canvas from crashing.
I now could disable and delete the initial theme.
As I said not ideal but it works well as a workaround for now.