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

[api-extractor] Internal Error: Unable to follow symbol for "const" on first api-extractor run #3875

Open
TimothyJones opened this issue Jan 6, 2023 · 16 comments
Labels
repro confirmed The issue comments included repro instructions, and the maintainers reproduced the problem

Comments

@TimothyJones
Copy link

Summary

When following the setup steps here, I encountered:

$  npx api-extractor run

api-extractor 7.33.7  - https://api-extractor.com/

Using configuration from ./api-extractor.json
Analysis will use the bundled TypeScript version 4.8.4

ERROR: Internal Error: Unable to follow symbol for "const"
You have encountered a software defect. Please consider reporting the issue to the maintainers of this application.

Repro steps

Because this happened on my first ever use of this tool, I haven't tried to make a minimal repro. However, I can point you at the repository that has this error.

Check out the api-extractor-issue branch of this repository, do npm install && npm run build and then run either npm run api-extractor, or npx api-extractor run --local --diagnostics

Expected result: No errors.

Actual result: as above. The end of the error message with --diagnostics is:

/Users/home/office/maintainer/case/node_modules/@types/stack-utils/index.d.ts
/Users/home/office/maintainer/case/node_modules/@types/yargs-parser/index.d.ts
/Users/home/office/maintainer/case/node_modules/@types/yargs/index.d.ts
============================================================

Ignoring reference to global variable "Array" in /Users/home/office/maintainer/case/src/connectors/contract/CaseContract.ts:43:13
Ignoring reference to global variable "Promise" in /Users/home/office/maintainer/case/src/connectors/contract/CaseContract.ts:46:6
Ignoring reference to global variable "Record" in /Users/home/office/maintainer/case/src/connectors/contract/structure/types.ts:6:18

ERROR: Internal Error: Unable to follow symbol for "const"
You have encountered a software defect. Please consider reporting the issue to the maintainers of this application.

As instructed, I am reporting it 😎

Details

  • I've tried to pin the typescript version to 4.8.4, but it didn't help (originally I was using 4.8.3).
  • It's possible that the autogenerated config file from api-extractor init is not right - for example, I had to change the /lib/ to /dist/. It would be awesome if the init would parse the tsconfig and set that setting (and any others) appropriately. I had a skim read of the settings, but couldn't see anything obviously wrong.
  • As far as I know, my tsconfig is set up correctly, and I'm not doing anything weird or advanced with the types. Of course, I might be wrong about this ;)
  • It would be an improvement if the error message that asks to report it to the maintainers pointed to this repository - it's not obvious at first that this is the place to report api-extractor issues.

Standard questions

Please answer these questions to help us investigate your issue more quickly:

Question Answer
@microsoft/api-extractor version? 7.33.7
Operating system? macOS 11.6.4, M1 mac
API Extractor scenario? Following the getting started instructions
Would you consider contributing a PR? Not at this time
TypeScript compiler version? 4.8.4
Node.js version (node -v)? v18.9.0
@TimothyJones
Copy link
Author

I also tried with node v16.19.0, and a completely clean install. Same error.

@jpikl-prgs
Copy link

I have the same issue in my project. It seems that API extractor is be unable to parse as const assertions. As a temporary workaround, I've removed all as const uses from input .d.ts file.

@pbklink
Copy link

pbklink commented Oct 3, 2023

Also encountered this error. In my case, the cause was due to imports of type import("./<file path>").<Type> in the *.d.ts files under the lib folder. This usage of import() in the lib files would occur when a type was used in a source file but not imported due to type inference. The solution was to explicitly specify the type and not rely on type inference.

As requested in AstSymbolTable.ts, I have tagged the commit in my Github repository where this error occurs. Tag is api-extractor-error. This error can be reproduced by:

  1. Cloning the repository (or downloading the tagged release)
  2. Checking out the tagged commit
  3. npm ci
  4. Run the script npm run dist which will force build and run api-extractor

This should generate the error.

The subsequent commit removes the relevant import()s from the lib files and fixes this issue for my project.

@octogonz octogonz added the repro confirmed The issue comments included repro instructions, and the maintainers reproduced the problem label Oct 4, 2023
@octogonz
Copy link
Collaborator

octogonz commented Oct 4, 2023

Sorry nobody looked at this until now.

I was able to confirm the repro from this issue's description. (I haven't tried @pbklink's repro yet.)

The problem is caused by the baseUrl setting in that project:

contract-case/tsconfig.json

{
  "extends": "@tsconfig/node16-strictest/tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "strict": true,
    "rootDir": "./src",
    "baseUrl": "src", 👈👈👈

This setting enables the following sort of import:

api-extractor-issue/src/boundaries/index.ts

export { CaseContract, CaseVerifier } from 'connectors/contract'; 👈👈👈
export * from './dsl/states';

Normally the module resolver would interpret connectors/contract to refer to an NPM package called connectors and then resolve to a path like node_modules/connectors/contract.d.ts.

The baseUrl remaps this import path to be resolved relative to src and thus import from api-extractor-issue/src/connectors/index.ts. It is one of those cute hacks that avoids the ../../.. awkwardness that is required for a standard module path like export { CaseContract, CaseVerifier } from '../connectors/contract';

The problem is that these remappings exist in tsconfig.json for your library project, but are generally NOT visible to the tsconfig.json used to build other projects that consume your library. (There is a proper way to define mappings in package.json, but that is a separate topic, with its own pitfalls.)

Now, API Extractor does actually consult your tsconfig.json when analyzing your project, but by design it tries to analyze your project as an external consumer would. In other words, it analyzes api-extractor-issue/dist/index.d.ts instead of api-extractor-issue/src/index.ts, and actually tsconfig.json is only meant to provide general context such as global typings.

And so the bug is that "baseUrl": "src" causes API Extractor to accidentally start analyzing .ts files instead of .d.ts files (because baseUrl redirects the resolver back into the src folder), which is what ultimately leads to the InternalError seen above.

So while we would probably NOT want to support "baseUrl": "src", we probably should make some fixes to improve this experience:

  • Print a warning when baseUrl is assigned
  • Report a hard error if the analyzer finds itself loading files with .ts extension instead of .d.ts extension, since this is just not going to work correctly
  • Maybe document these requirements better on the website

In short, this repo's tsconfig.json is using an compiler configuration that is nonstandard and cannot generalize to the professional library development situations that API Extractor focuses on, so my recommendation is to fix the tsconfig.json to use standard imports, and then the crash will go away.

@TimothyJones
Copy link
Author

Aha! Thanks for the explanation. I thought I had fixed the exports so that external consumers can use it appropriately, but perhaps I didn't. I remember looking in to that problem at length.

by design it tries to analyze your project as an external consumer would.

This definitely wasn't clear to me!

I really like your three improvement steps.

@TimothyJones
Copy link
Author

Update: It turns out I fixed it by removing that baseUrl in a later commit. And, API extractor does indeed work on the current head of main. Thank you for the pointer!

@cdauth
Copy link

cdauth commented Mar 29, 2024

I'm experiencing the same problem in my repository FacilMap/facilmap. How to reproduce: Check out the repository at tag v4.0.0, run yarn install, then run yarn build. The error happens during the build of the leaflet and frontend modules. As far as I'm aware, I am not using the baseUrl property.

After some investigation, I found the cause to be one specific as const statement, which I fixed in this commit.

@johnwc
Copy link

johnwc commented Dec 7, 2024

@octogonz We use alias paths in our tsconfig, like example below, to help avoid with the ../../ nuances. When we have the imports using ~/ we see the Unable to follow symbol for "const" error, but when we change the import to a ../../../ the error does not occur. How can we use aliases like this, and still use api-extractor?

{
    ...
    "compilerOptions": {
        ...
        "paths": {
            "@/*": [ "./assets/*" ],
            "~/*": [ "./src/*" ]
        },
    }
}
import * as utils from '~/utilities'
...

@michaelparkadze
Copy link

This took a long time to find, thank you @octogonz for the clear explanation!

@johnwc
Copy link

johnwc commented Jan 10, 2025

@octogonz any thoughts on my question?

@TimothyJones
Copy link
Author

@johnwc I think your question is already answered- as far as I understand, paths doesn’t change the output mapping, so the answer already posted (although about a different compiler option) still applies.

@johnwc
Copy link

johnwc commented Jan 11, 2025

@johnwc I think your question is already answered- as far as I understand, paths doesn’t change the output mapping, so the answer already posted (although about a different compiler option) still applies.

@TimothyJones you're going to have to explain further, as I don't know what you're referring to with paths doesn’t change the output mapping. Where did changing output mapping come up?

My question is how can we use aliases with import statements and still have api-extractor work with rolling up the declarations into single file? Using aliases in import statements is very common.

@laviddichterman
Copy link

I'm running into a similar issue, but I'm not sure if it's the same:

x Build failed in 2.15s
error during build:
[vite:dts] Internal Error: Unable to follow symbol for "DateFnsLocale"

I'm using vite-plugin-dts to build a UX library. Part of that library includes subclassing the DateFns adapter here:
https://github.com/mui/mui-x/blob/61346b398890959a2305f960ac14aaf77aaed6eb/packages/x-date-pickers/src/AdapterDateFnsV3/AdapterDateFnsV3.ts

My code:

import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
import { DateBuilderReturnType } from '@mui/x-date-pickers/models';
import { toDate as toDateBase } from 'date-fns';

export const AdapterCurrentTimeOverrideUtils = (now: Date | number) =>
  class AdapterDateFnsWrapper extends AdapterDateFns {
    public date = <T extends string | null | undefined>(
      value?: T,
    ): DateBuilderReturnType<T, Date> => {
      type R = DateBuilderReturnType<T, Date>;
      if (typeof value === 'undefined') {
        return <R>toDateBase(now);
      }

      if (value === null) {
        return <R>null;
      }

      return <R>new Date(value);
    };
  };

Basically, I'm hoping someone can confirm to me that this is indeed the same issue and I should sit tight and wait for this bug to be addressed.

@mpdata7
Copy link

mpdata7 commented Feb 15, 2025

I fixed this problem by changing line in vite.config.ts
plugins: [vue(), cssInjectedByJsPlugin(), dts({ rollupTypes: true })],

to
plugins: [vue(), cssInjectedByJsPlugin(), dts()],

And also I have changed in package.json
"types": "./dist/index.d.ts",

to
"types": "./dist/src/index.d.ts",

The problem was related to vite-plugin-dts with enabled rollupTypes, and it was too difficult to fix the bug, so I just decided to disable rollupTypes

@johnwc
Copy link

johnwc commented Feb 15, 2025

I fixed this problem by changing line in vite.config.ts plugins: [vue(), cssInjectedByJsPlugin(), dts({ rollupTypes: true })],

to plugins: [vue(), cssInjectedByJsPlugin(), dts()],

And also I have changed in package.json "types": "./dist/index.d.ts",

to "types": "./dist/src/index.d.ts",

The problem was related to vite-plugin-dts with enabled rollupTypes, and it was too difficult to fix the bug, so I just decided to disable rollupTypes

You didn't fix the error, you disabled the feature that has the error. That is what most have to do to get it to work, but we are wanting to rollup all of the types into one file.

@mpdata7
Copy link

mpdata7 commented Feb 16, 2025

You didn't fix the error, you disabled the feature that has the error. That is what most have to do to get it to work, but we are wanting to rollup all of the types into one file.

This topic ranks top 1 on Google for many queries related to "Internal Error: Unable to follow symbol for." I spent 2 days trying to solve my issue with the incorrect behavior of the API extractor, went through a ton of threads online. And it was a revelation for me that in my case, I could simply disable rollupTypes. If someone had mentioned this in this thread earlier, I would have saved 2 days of my life.

It is not obvious for many non experts in typescript, that they could just disable rollupTypes, and this would solve lots of theis problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repro confirmed The issue comments included repro instructions, and the maintainers reproduced the problem
Projects
Status: AE/AD
Development

No branches or pull requests

9 participants