Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug(cdk): [ERROR] TS-993004: Unable to import directive in 19.2.4 #30663

Closed
1 task done
jeremyhofer opened this issue Mar 19, 2025 · 18 comments · Fixed by #30667 or #30679
Closed
1 task done

bug(cdk): [ERROR] TS-993004: Unable to import directive in 19.2.4 #30663

jeremyhofer opened this issue Mar 19, 2025 · 18 comments · Fixed by #30667 or #30679
Assignees
Labels
area: build & ci Related the build and CI infrastructure of the project in progress This issue is currently in progress P2 The issue is important to a large percentage of users, with a workaround

Comments

@jeremyhofer
Copy link

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

19.2.3

Description

Upgrading to 19.2.4 from 19.2.3 introduces compilation errors. On my local project the compilation issue is related to CdkFixedSizeVirtualScroll used by CDK overlay, but testing on stack blitz it appears to be an issue with many different directives.

Error message from my local project:

✘ [ERROR] TS-993004: Unable to import directive CdkFixedSizeVirtualScroll.
  The symbol is not exported from ./node_modules/@angular/cdk/overlay/index.d.ts
(module '@angular/cdk/overlay'). [plugin angular-compiler]

In a fresh stack blitz recreation w/ CDK 19.2.4 I am seeing the following:

✘ [ERROR] TS-993004: Unable to import directive CdkScrollable.
  The symbol is not exported from /home/projects/components-issue-starter-mzddipx4/node_modules/@angular/cdk/drag-drop/index.d.ts (module '@angular/cdk/drag-drop'). [plugin angular-compiler]

I suspect the issue was introduced via this commit/PR:

Reproduction

StackBlitz link: https://stackblitz.com/edit/components-issue-starter-mzddipx4?file=package.json
Steps to reproduce:

  1. Simply open the example. The default project w/ latest 19.2.x dependencies fails to compile

Expected Behavior

No regressions should be present in a bugfix release.

Actual Behavior

A regression preventing application compilation has been introduced.

Environment

Angular CLI: 19.2.4
Node: 22.14.0
Package Manager: npm 10.9.2
OS: linux x64

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

Package Version

@angular-devkit/architect 0.1902.4
@angular-devkit/build-angular 19.2.4
@angular-devkit/core 19.2.4
@angular-devkit/schematics 19.2.4
@angular/cdk 19.2.4
@angular/cli 19.2.4
@angular/material 19.2.4
@angular/ssr 19.2.4
@angular/youtube-player 19.2.4
@schematics/angular 19.2.4
rxjs 7.8.2
typescript 5.8.2

@jeremyhofer jeremyhofer added the needs triage This issue needs to be triaged by the team label Mar 19, 2025
@jeremyhofer jeremyhofer changed the title bug(cdk): [ERROR] TS-993004: Unable to import directive bug(cdk): [ERROR] TS-993004: Unable to import directive in 19.2.4 Mar 19, 2025
@devversion
Copy link
Member

Thanks for the issue. Are you by any chance actually relying on some of the scrolling symbols being re-exported from the OverlayModule?

I feel like the Stackblitz start is not representative because it does seem to differ from an Angular CLI app. See:

In the real ng CLI app, I think it only surfaces if you use some of the re-exported directives, right?

@crisbeto crisbeto added P2 The issue is important to a large percentage of users, with a workaround area: build & ci Related the build and CI infrastructure of the project and removed needs triage This issue needs to be triaged by the team labels Mar 20, 2025
@frunjik
Copy link

frunjik commented Mar 20, 2025

Just extra info - I am using Overlay in app
ng build - works
ng serve - fails

@devversion
Copy link
Member

@frunjik Thank you! We found out that it's HMR triggering this (but it's still an issue from Angular CDK/Material; HMR works as expected)

@devversion devversion self-assigned this Mar 20, 2025
@MatteoBarbieriSacmi
Copy link

I'm having the same problem just by upgrading Angular from 19.2.3 to 19.2.4
X [ERROR] TS-993004: Unable to import directive CdkPortal.
The symbol is not exported from D://node_modules/@angular/cdk/dialog/index.d.ts (module '@angular/cdk/dialog'). [plugin angular-compiler]

@jeremyhofer
Copy link
Author

Double checked / confirmed - only an issue with HMR in the dev-server.

In my use case I am only using directives supplied directly from the OverlayModule, no direct references to scrolling symbols.

My template leveraging overlay:

<button
  mat-button
  class="dropbtn"
  (mouseenter)="buttonMouseEnter()"
  (mouseleave)="buttonMouseLeave()"
  cdkOverlayOrigin
  #trigger="cdkOverlayOrigin"
>
  {{ link().name }}
</button>
<ng-template
  cdkConnectedOverlay
  [cdkConnectedOverlayOrigin]="trigger"
  [cdkConnectedOverlayOpen]="isOpen()"
  (detach)="detach()"
>
  <div
    class="dropdown-content"
    (mouseenter)="dropdownMouseEnter()"
    (mouseleave)="dropdownMouseLeave()"
  >
    @for (sublink of link().sublinks; track $index) {
      <a
        mat-menu-item
        [routerLink]="sublink.url"
        routerLinkActive="active"
        (click)="linkClick()"
        >{{ sublink.name }}</a
      >
    }
  </div>
</ng-template>

Only reference to cdk in my component class is the OverlayModule import in the component.

@devversion devversion added the in progress This issue is currently in progress label Mar 20, 2025
devversion added a commit to devversion/material2 that referenced this issue Mar 20, 2025
As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Fixes angular#30663.
@bellib
Copy link

bellib commented Mar 20, 2025

I'm having the same problem just by upgrading Angular from 19.0.0 to 19.2.4 X [ERROR] TS-993004: Unable to import directive CdkPortal. The symbol is not exported from D://node_modules/@angular/cdk/dialog/index.d.ts (module '@angular/cdk/dialog'). [plugin angular-compiler]

devversion added a commit to devversion/material2 that referenced this issue Mar 20, 2025
As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Inside Google, the latter approach is automatically emitted by the
compiler, when everything is built from source; but that's not usable
here; but confirms this approach as being reasonable. Ideally we will
stop re-exporting modules in APF packages, and long-term we start
supporting the proper module guessing with relative imports.

Fixes angular#30663.
@devversion
Copy link
Member

FYI: Fix is pending and we'll soon cut another patch. Thanks everybody! See #30667

@TruongNguyen888
Copy link

i am running into this error too.
Updated from 19.1 to 19.2.4

devversion added a commit to devversion/material2 that referenced this issue Mar 20, 2025
As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Inside Google, the latter approach is automatically emitted by the
compiler, when everything is built from source; but that's not usable
here; but confirms this approach as being reasonable. Ideally we will
stop re-exporting modules in APF packages, and long-term we start
supporting the proper module guessing with relative imports.

Fixes angular#30663.
devversion added a commit to devversion/material2 that referenced this issue Mar 20, 2025
As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Inside Google, the latter approach is automatically emitted by the
compiler, when everything is built from source; but that's not usable
here; but confirms this approach as being reasonable. Ideally we will
stop re-exporting modules in APF packages, and long-term we start
supporting the proper module guessing with relative imports.

Fixes angular#30663.
devversion added a commit that referenced this issue Mar 20, 2025
)

As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Inside Google, the latter approach is automatically emitted by the
compiler, when everything is built from source; but that's not usable
here; but confirms this approach as being reasonable. Ideally we will
stop re-exporting modules in APF packages, and long-term we start
supporting the proper module guessing with relative imports.

Fixes #30663.
devversion added a commit that referenced this issue Mar 20, 2025
As of recently, we switched our imports from module imports to relative
imports, when inside the same package. This is expected for proper code
splitting, and also for our upcoming `rules_js` migration.

Unfortunately this highlights an issue with the Angular compiler. We
occasionally re-export other entry-point modules from one entry-point
module. This is likely done for convenience, but we should stop doing
that going forward (and likely will naturally resolve this over time
with standalone either way).

The problem is that the Angular compiler, especially with HMR enabled
(i.e. no tree-shaking of imports), will try to generate imports in the
user code to symbols that are indirectly re-exported. This worked before
because the Angular compiler leveraged the "best guessed module", based
on the "last module import" it saw before e.g. discovering the
re-exported `ScrollingModule`; hence it assumed all exports of that
module are available from `@angular/cdk/scrolling`. This assumption no
longer works because the last module import would be e.g. `cdk/overlay`,
which relatively imports from scrolling to re-export the module then.

There are a few options:

- teach the compiler about relative imports inside APF packages with
  secondary entry-points. Possible, but won't work for users with older
  compiler versions. Maybe a long-term good thing to do; on the other
  hand, standalone is the new future.

- switch back to module imports. Not possible and relative imports
  should work inside a package IMO.

- re-export the exposed symbols, under a private name. This is the
  easiest approach and there also aren't a lot of module re-exports; so
  this is a viable approach taken by this commit.

Inside Google, the latter approach is automatically emitted by the
compiler, when everything is built from source; but that's not usable
here; but confirms this approach as being reasonable. Ideally we will
stop re-exporting modules in APF packages, and long-term we start
supporting the proper module guessing with relative imports.

Fixes #30663.
@devversion
Copy link
Member

Hey all, I've just cut a new release. Can you please verify and report back here? Sorry for the inconveniences!

@dailytabs
Copy link

Works for me!

@submarines-and
Copy link

submarines-and commented Mar 21, 2025

Same error for me using 19.2.5

Image

@isham-mohamed
Copy link

isham-mohamed commented Mar 21, 2025

Same error for me using 19.2.5

Image

same on my project.

@devversion
Copy link
Member

I tested and it was really hard to reproduce (and even our internal didn't catch it) because it only happens if imports to the Angular CDK happen in a specific order.

I've confirmed that it's only the cdk/overlay and the Dir directive; so a good workaround might be to import the Bidi module directly temporarily?

devversion added a commit to devversion/material2 that referenced this issue Mar 21, 2025
…e imported

This is a follow-up to cb3b0a8 which
did miss this transitive re-export of the `Dir` directive. The compiler
will try the last module import, so even if e.g. `./scrolling`
re-exported `Dir` as of the initial commit, the compiler would try
importing via `@angular/cdk/overlay`.

This commit fixes this remaining instance, and updates the new testing
infrastructure to import/test every module in isolation. The tests
didn't notice that issue because the compiler discovered the `Dir`
directive/"Reference" already via another import that "worked".

Fixes angular#30663.
@devversion
Copy link
Member

Created a PR for this: #30679. This should be the last one; also improved the new tests that I've created as part of this report.

devversion added a commit to devversion/material2 that referenced this issue Mar 21, 2025
…e imported

This is a follow-up to cb3b0a8 which
did miss this transitive re-export of the `Dir` directive. The compiler
will try the last module import, so even if e.g. `./scrolling`
re-exported `Dir` as of the initial commit, the compiler would try
importing via `@angular/cdk/overlay`.

This commit fixes this remaining instance, and updates the new testing
infrastructure to import/test every module in isolation. The tests
didn't notice that issue because the compiler discovered the `Dir`
directive/"Reference" already via another import that "worked".

Fixes angular#30663.
@TruongNguyen888
Copy link

Hey all, I've just cut a new release. Can you please verify and report back here? Sorry for the inconveniences!

For me its working now again with 19.2.5.
Thank you for the fast fix.

@MatteoBarbieriSacmi
Copy link

19.2.5 works for me too. Thanks

devversion added a commit that referenced this issue Mar 21, 2025
…e imported (#30679)

This is a follow-up to cb3b0a8 which
did miss this transitive re-export of the `Dir` directive. The compiler
will try the last module import, so even if e.g. `./scrolling`
re-exported `Dir` as of the initial commit, the compiler would try
importing via `@angular/cdk/overlay`.

This commit fixes this remaining instance, and updates the new testing
infrastructure to import/test every module in isolation. The tests
didn't notice that issue because the compiler discovered the `Dir`
directive/"Reference" already via another import that "worked".

Fixes #30663.
devversion added a commit that referenced this issue Mar 21, 2025
…e imported (#30679)

This is a follow-up to cb3b0a8 which
did miss this transitive re-export of the `Dir` directive. The compiler
will try the last module import, so even if e.g. `./scrolling`
re-exported `Dir` as of the initial commit, the compiler would try
importing via `@angular/cdk/overlay`.

This commit fixes this remaining instance, and updates the new testing
infrastructure to import/test every module in isolation. The tests
didn't notice that issue because the compiler discovered the `Dir`
directive/"Reference" already via another import that "worked".

Fixes #30663.

(cherry picked from commit 1e5082d)
@RushiGhuge
Copy link

it's working now!

@frunjik
Copy link

frunjik commented Mar 24, 2025

solved with cdk 19.2.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: build & ci Related the build and CI infrastructure of the project in progress This issue is currently in progress P2 The issue is important to a large percentage of users, with a workaround
Projects
None yet