Theme SDC instances cause fatal error after theme uninstallation due to core bug: keep in-use Components and switch them to the Fallback ComponentSource
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3546188. -->
Reported by: [mherchel](https://www.drupal.org/user/118428)
Related to !148
>>>
<h3 id="overview">Steps to reproduce</h3>
<ol>
<li>Install <a href="https://github.com/phenaproxima/xb-demo">https://github.com/phenaproxima/xb-demo</a></li>
<li>Go to appearance, change default theme to Olivero</li>
<li>Uninstall the "Starshot Demo" and "CivicTheme" themes</li>
<li>Go to homepage and see errors</li>
</ol>
<h3>Errors</h3>
<pre>The website encountered an unexpected error. Try again later.<br><br>AssertionError: assert($component instanceof Component) in assert() (line 440 of modules/contrib/canvas/src/Plugin/Field/FieldType/ComponentTreeItemList.php).<br>Drupal\canvas\Plugin\Field\FieldType\ComponentTreeItemList->getHydratedValue() (Line: 354)<br>Drupal\canvas\Plugin\Field\FieldType\ComponentTreeItemList->getHydratedTree() (Line: 191)<br>Drupal\canvas\Plugin\Field\FieldType\ComponentTreeItemList->toRenderable() (Line: 28)<br>Drupal\canvas\Plugin\Field\FieldFormatter\NaiveComponentTreeFormatter->viewElements() (Line: 91)<br>Drupal\Core\Field\FormatterBase->view() (Line: 275)<br>Drupal\Core\Entity\Entity\EntityViewDisplay->buildMultiple() (Line: 288)<br>Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay->buildMultiple() (Line: 341)<br>Drupal\Core\Entity\EntityViewBuilder->buildComponents() (Line: 283)<br>Drupal\Core\Entity\EntityViewBuilder->buildMultiple() (Line: 240)<br>Drupal\Core\Entity\EntityViewBuilder->build()<br>call_user_func_array() (Line: 107)<br>Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 871)<br>Drupal\Core\Render\Renderer->doCallback() (Line: 433)<br>Drupal\Core\Render\Renderer->doRender() (Line: 222)<br>Drupal\Core\Render\Renderer->render() (Line: 242)<br>Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 622)<br>Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 235)<br>Drupal\Core\Render\MainContent\HtmlRenderer->prepare() (Line: 131)<br>Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)<br>Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray() (Line: 246)<br>Symfony\Component\EventDispatcher\EventDispatcher::Symfony\Component\EventDispatcher\{closure}() (Line: 206)<br>Symfony\Component\EventDispatcher\EventDispatcher->callListeners() (Line: 56)<br>Symfony\Component\EventDispatcher\EventDispatcher->dispatch() (Line: 188)<br>Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)<br>Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)<br>Drupal\Core\StackMiddleware\Session->handle() (Line: 48)<br>Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)<br>Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)<br>Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 116)<br>Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 90)<br>Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)<br>Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)<br>Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 53)<br>Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)<br>Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 715)<br>Drupal\Core\DrupalKernel->handle() (Line: 19)</pre><p>XB editor gives errors (but doesn't die)</p>
<p><img src="https://www.drupal.org/files/issues/2025-09-11/Cursor_and_Drupal_Canvas.png" alt></p>
<h3 id="proposed-resolution">Proposed resolution</h3>
<p>I know that there's a valid reason this is failing (the components don't exist anymore), but this is a use case that people will run into and there is no way to recover unless you know Drupal well enough to go back to /admin</p>
<p>A realistic scenario is the following:</p>
<ol>
<li>User downloads Drupal CMS</li>
<li>Drupal CMS comes with prebuilt homepage in Canvas with components from Mercury</li>
<li>User wants to change themes. Installs new theme</li>
<li>Uninstalls old theme. </li>
<li>Site dead. No way for non-technical user to recover.</li>
<li>User is frustrated and throws their monitor across the room</li>
<li>User picks up monitor, and goes to wordpress.com</li>
<li>User gets coffee and breakfast and then creates a WP website while having a negative experience of Drupal. </li>
<li>User tells all their friends over a game of golf.</li>
<li>One friend is the CEO of Megacorp Inc, which was evaluating Drupal.</li>
<li>Megacorp CEO decides to go with AEM.</li>
<li>Drupal is sad.</li>
</ol>
<p>Handling this like <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/experience_builder/issues/3519168" title="Status: Closed (fixed)">#3519168: Handle components provided by ComponentSources EXPLICITLY disappearing — enables deleting JS components that are in use</a></span>, not like <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3470422" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3470422</a></span>: in-use <code>Component</code>s should switch to the <code>Fallback</code> source, ensuring graceful degradation. The user then has the choice:</p>
<ol>
<li>either reinstall the theme, this will cause all <code>Component</code>s that were switched to the fallback to start working for real again, as if nothing happened 🪄
</li><li>or allow content authors to find all component instances (using <code>/admin/appearance/component</code>) and replace them with something else.<br>
<h3 id="ui-changes">User interface changes</h3>
<p>Don't make Drupal sad. Lets make it fail gracefully:</p>
<ol>
<li>Before uninstallation: <img src="https://www.drupal.org/files/issues/2025-10-03/Screenshot%202025-10-03%20at%201.01.22%20PM.png"> (the red-ish component instance)
</li><li>Uninstall the theme providing that SDC. Uninstallation shows nothing different in the UI
</li><li>Canvas UI: recovery is now possible: <img src="https://www.drupal.org/files/issues/2025-10-03/Screenshot%202025-10-03%20at%201.02.44%20PM.png">
</li><li>Live site: nothing to see — if this SDC had slots, then the contents of those slots would've been rendered. <img src="https://www.drupal.org/files/issues/2025-10-03/Screenshot%202025-10-03%20at%201.05.25%20PM.png">
</li></ol>
</li></ol>
> Related issue: [Issue #3528723](https://www.drupal.org/node/3528723)
> Related issue: [Issue #3528499](https://www.drupal.org/node/3528499)
> Related issue: [Issue #3550019](https://www.drupal.org/node/3550019)
> Related issue: [Issue #3519168](https://www.drupal.org/node/3519168)
issue