rushstack icon indicating copy to clipboard operation
rushstack copied to clipboard

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

Open TimothyJones opened this issue 2 years ago • 17 comments
trafficstars

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 avatar Jan 06 '23 07:01 TimothyJones

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

TimothyJones avatar Jan 06 '23 07:01 TimothyJones

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.

jpikl-prgs avatar Feb 01 '23 17:02 jpikl-prgs

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.

pbklink avatar Oct 03 '23 02:10 pbklink

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.

octogonz avatar Oct 04 '23 05:10 octogonz

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 avatar Oct 04 '23 06:10 TimothyJones

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!

TimothyJones avatar Oct 04 '23 06:10 TimothyJones

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.

cdauth avatar Mar 29 '24 10:03 cdauth