Skip to content

bug: elm.attachShadow is not a function TypeError in Angular SSR app since Ionic v8.2.4 #29751

Closed

Description

@SebastianKohler

Prerequisites

Ionic Framework Version

v8.x

Current Behavior

Since v8.2.4 Ionic components like ion-button and ion-chip produce an elm.attachShadow is not a function TypeError in Angular apps with server side rendering (SSR) enabled.

The TypeError did not occur in version 8.2.2 and prior, but in every version since 8.2.4.

Expected Behavior

No TypeError like in v8.2.2 and prior.

Steps to Reproduce

See the code reproduction URL for a minimal app on GitHub showcasing the error (steps to run the app in the README).

The modules-based Angular app was generated with Angular CLI version 18.1.3 with the command:

ng new ionic-angular-ssr-attachShadow-typeError --ssr=true --standalone=false --style=scss

I then added @ionic/angular and @ionic/angular-server, configured Ionic and switched to Angular’s older browser builder which I’m using in my actual project (and as far as I know Ionic doesn’t work in Angular standalone SSR apps using the new Vite-based application builder). See the commit history in the code reproduction repository for a detailed account of the code changes.

Once you have the code reproduction app running you will get the TypeError in the terminal.

Code Reproduction URL

https://github.com/SebastianKohler/ionic-angular-ssr-attachShadow-typeError

Ionic Info

I don’t use the Ionic CLI. Here is the info from the Angular CLI:

Angular CLI: 18.1.3
Node: 20.12.1
Package Manager: npm 10.7.0
OS: win32 x64

Angular: 18.1.3
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router, ssr

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1801.3
@angular-devkit/build-angular   18.1.3
@angular-devkit/core            18.1.3
@angular-devkit/schematics      18.1.3
@schematics/angular             18.1.3
rxjs                            7.8.1
typescript                      5.5.4
zone.js                         0.14.10

Additional Information

No response

Activity

  1. crufter commented on Oct 2, 2024

    @crufter

    This is affecting us as well - SSR cannot render the site.

  2. AndrusGerman commented on Oct 11, 2024

    @AndrusGerman

    Same problem

  3. kafumanto commented on Oct 24, 2024

    @kafumanto

    Same problem here.

    In addition, building the app catches the error also at compile time:

    > ng build my-app --watch
    
    TypeError: o.attachShadow is not a function
        at Mu (file:///[redacted]/.angular/prerender-root/d62c222d-bf22-49a2-84e2-4076e9839a1f/chunk-RESHKSIQ.mjs:2:26911)
    [...]
    

    EDIT: if helpful, here a more detailed stack-trace:

    TypeError: elm.attachShadow is not a function
        at proxyHostElement ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:1993:15)
        at patchElement2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2104:17)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2110:13)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2113:15)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2113:15)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2113:15)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2113:15)
        at patchChild2 ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2113:15)
        at hydrateApp ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:2144:9)
        at hydrateAppClosure ([redacted]\.angular\cache\18.2.9\[redacted]\vite\deps_ssr\@ionic_angular-server.js:30085:5)
    

    Not sure if it's helpful, since the error looks like a compile-time error anyway: my root app component has host: { ngSkipHydration: 'true' }, and the error is reported at run-time inside the hydrateApp() function (that I suppose shouldn't be executed at runtime given the above setting).

  4. Watchwolf commented on Nov 25, 2024

    @Watchwolf

    Same problem for me with the latest ionic version.

  5. davidquintard commented on Dec 5, 2024

    @davidquintard

    same problem

  6. davidquintard commented on Mar 1, 2025

    @davidquintard

    no workaround ?

  7. SebastianKohler commented on Mar 5, 2025

    @SebastianKohler
    ContributorAuthor

    My guess is that this originates from Stencil, and apparently the Ionic team is working on improving the Stencil SSR performance: https://ionic.io/blog/coming-soon-new-updates-features-for-ionics-open-source-projects

    Let's hope the current Stencil work will fix this ...

  8. kafumanto commented on Mar 5, 2025

    @kafumanto

    I suspect that no one at Ionic has been looking into bug reports for a long time...

  9. crufter commented on Mar 5, 2025

    @crufter

    Probably not applicable to most but in my case the project is a website so I solved this by removing ionic and moving to angular material...

  10. davidquintard commented on Mar 5, 2025

    @davidquintard

    For my part, i downgraded to ionic 8.2.2.
    It works fine.

  11. Watchwolf commented on Mar 5, 2025

    @Watchwolf

    I solved this by removing ssr. I have written a script to generate static page and redirect the search engine to them.

  12. SebastianKohler commented on Mar 5, 2025

    @SebastianKohler
    ContributorAuthor

    I also pinned version 8.2.2, which is fine for now. Thinking about moving to Angular Material, but it's so much work in the case of my project.

  13. SebastianKohler commented on Jun 6, 2025

    @SebastianKohler
    ContributorAuthor

    Still get the error in Ionic 8.6.0, though slightly different:

    TypeError: this.attachShadow is not a function
        at ctor.createShadowRoot (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:180912)
        at proxyHostElement (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:241935)
        at patchElement2 (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:243771)
        at patchChild2 (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:243843)
        at patchChild2 (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:243933)
        at patchChild2 (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:243933)
        at patchChild2 (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:243933)
        at hydrateApp (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:246891)
        at hydrateAppClosure (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:1397098)
        at hydrateFactory (C:\Users\xxxxxx\GitHub\ionic-angular-ssr-attachShadow-typeError\dist\app\server\main.js:1:1397205)
    
  14. DavidBowdoin commented on Jul 2, 2025

    @DavidBowdoin

    v8.2.2 was released a year ago and we have not been able to update since. I hope this does not mean ionic SSR is dead in the future? Does anyone know how to fix the ionic SSR code to work with @stencil/core > 4.20.0 I believe that is the root issue.

    We depend on SSR (server side rendering) so we remain
    pinned "@ionic/angular": "8.2.2"
    and overrides: "@stencil/core": "4.20.0"

  15. SebastianKohler commented on Feb 20, 2026

    @SebastianKohler
    ContributorAuthor

    I drilled into this with the help of gpt-5.3-codex. You can read what it found below. The primary target for fixing this is in Stencil, because the failing code path is in the Stencil hydrate runtime, but Ionic could also add a guard/workaround in packages/angular-server/src/ionic-server-module.ts. I will open a new issue with Stencil and hope they fix this, since the Ionic team doesn't seem too active about it.

    gpt-5.3-codex report on this bug

    I investigated this further and can confirm this is a regression introduced after Ionic 8.2.2 when used with Angular SSR (@angular/ssr + @ionic/angular-server).

    What I found

    • @ionic/angular-server calls hydrateDocument(doc, ...) from @ionic/core/hydrate.
    • In newer versions (e.g. 8.7.17), hydration goes through Stencil’s proxyHostElement -> createShadowRoot -> this.attachShadow(...).
    • On Angular SSR, the server Document is Domino-based, and those elements do not have attachShadow.
    • Result: SSR crashes with TypeError: this.attachShadow is not a function as soon as an Ionic component is present on the rendered page.
    • Pinning to 8.2.2 avoids the crash.

    Why 8.2.2 works

    In the older hydrate path, shadow host setup used SSR-safe fallback behavior instead of directly calling attachShadow on the external server DOM element.

    Relevant source location

    This appears to come from Stencil hydrate runtime behavior:

    • src/hydrate/platform/proxy-host-element.ts (calls createShadowRoot)
    • src/utils/shadow-root.ts (createShadowRoot calls attachShadow)

    Example file:
    https://github.com/stenciljs/core/blob/4d322a75878cc14604c7b2cd747cdc3c17249fa5/src/hydrate/platform/proxy-host-element.ts

    Request

    Could Ionic add a guard/workaround in packages/angular-server/src/ionic-server-module.ts (or otherwise coordinate with Stencil) so Angular SSR users are not broken on current Ionic 8.x while the Stencil-side hydrate fix is addressed?

  16. SebastianKohler commented on Feb 20, 2026

    @SebastianKohler
    ContributorAuthor

    Quick update after discussing this with Stencil:

    I created and shared a minimal repro and got clarification from Stencil that SSR DOM environments without modern custom-element primitives (notably attachShadow) are considered out of scope for hydrateDocument(...) support. So this is not expected to be fixed upstream in Stencil for Domino-like DOMs (including Angular SSR’s current server DOM environment).

    Following Stencil’s suggestion (thanks @johnjenkins), I tested an Ionic-side mitigation using serializeShadowRoot: 'scoped': https://stenciljs.com/docs/hydrate-app#serializeshadowroot

    In Ionic Angular SSR, this is the place where it applies:

    // packages/angular-server/src/ionic-server-module.ts
    return hydrateDocument(doc, {
      clientHydrateAnnotations: false,  // also tested true, see notes below
      serializeShadowRoot: 'scoped',
      excludeComponents: [
        // ...
      ],
    });

    Result in my repro:

    • It avoids the server crash (TypeError: this.attachShadow is not a function).
    • But it is not a complete fix in Angular SSR + Ionic: after client upgrade, rendered output is incorrect (duplicate internals, e.g. extra <button> outside the shadow root for ion-button).
    • I also tested clientHydrateAnnotations: true; this did not resolve the client mismatch in this repro.

    So the current state is:

    • declarative-shadow-dom path crashes on server with Angular SSR DOM.
    • scoped avoids crash but causes client/render correctness issues.

    Given Stencil’s scope clarification, this now looks like an Ionic Angular SSR integration issue in @ionic/angular-server (how hydrateDocument is invoked and how SSR DOM compatibility is handled).

    Could maintainers please triage this and suggest/implement a supported integration path for Angular SSR?

  17. SebastianKohler commented on Feb 23, 2026

    @SebastianKohler
    ContributorAuthor

    Correction/update to my previous comment (I reran everything from clean state and found my earlier conclusion on scoped+annotations was incomplete).

    What I can now reproduce reliably:

    1. Default path (serializeShadowRoot default / DSD):
    • server crashes with: TypeError: this.attachShadow is not a function
    1. Scoped path:
    hydrateDocument(doc, {
      serializeShadowRoot: 'scoped',
      clientHydrateAnnotations: true,
      // ...
    });
    • avoids the server crash
    • and fixes the earlier duplicate-internals symptom (no extra light-DOM <button> after upgrade)

    However, there is still a client hydration error from Angular:
    TypeError: Cannot read properties of undefined (reading 'hasAttribute')
    (stack points into Angular hydration internals / ngSkipHydration checks)

    Important confirmation:

    • if I remove provideClientHydration() from the Angular app, this error disappears.

    So there appear to be two separate Angular+Ionic SSR integration issues:

    • server-side DSD incompatibility with current Angular SSR DOM (attachShadow missing)
    • client-side Angular hydration mismatch after Ionic SSR processing (even when scoped+annotations is used)

    Given Stencil’s scope clarification, this still looks like an Ionic Angular SSR integration problem in @ionic/angular-server (option defaults and hydration compatibility with Angular SSR/client hydration).

    I pushed a branch with a minimal diagnostic patch (IonicServerScopedModule) showing the scoped+annotations behavior and remaining Angular hydration error: SebastianKohler/ionic-angular-ssr-attachShadow-typeError@a11b419

  18. SebastianKohler commented on Feb 23, 2026

    @SebastianKohler
    ContributorAuthor

    Follow-up with new findings from Stencil investigation:

    The Angular client error (TypeError: Cannot read properties of undefined (reading 'hasAttribute')) appears to be caused by a Stencil non-shadow patching bug affecting .children/.childNodes (notably with ion-app), which was fixed in Stencil 4.40.0. Ionic 8.7.17 ships Stencil 4.38.0.

    This suggests a concrete Ionic fix path:

    1. In @ionic/angular-server, use serializeShadowRoot: 'scoped', and
    2. Set clientHydrateAnnotations: true.
    3. Upgrade Ionic’s bundled Stencil runtime to >= 4.40.0.
  19. SebastianKohler commented on Aug 24, 2026

    @SebastianKohler
    ContributorAuthor

    Completed in #30967.

  20. ionitron-bot commented on Sep 23, 2026

    @ionitron-bot

    Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

  21. locked and limited conversation to collaborators on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions