ember-cli-typescript icon indicating copy to clipboard operation
ember-cli-typescript copied to clipboard

Type errors crash the build on Ember CLI 3.15+

Open NullVoxPopuli opened this issue 3 years ago β€’ 17 comments

Edit by @chriskrycho:* original title was "Does not appear to work with Ember 3.27". Updated to reflect the actual underlying issue in Ember CLI.

Please paste the output of ember -v here

❯ ember -v
ember-cli: 3.27.0
node: 12.20.2
os: linux x64

Please paste the output of tsc -v here

❯ yarn tsc -v

Version 4.3.5

Please paste the version of ember-cli-typescript and ember-cli-typescript-blueprints here

4.2.1 blueprints package removed

Please paste your tsconfig.json and tslint.json or eslint.json (if applicable) below

default w/ 4.2.1

What are instructions we can follow to reproduce the issue?

Repro is these changes: https://github.com/NullVoxPopuli/ember-play/pull/5/commits/8dcf53e06fd9f40182dd29e0a99aeb8fe8e5a94b

git clone [email protected]:NullVoxPopuli/ember-play.git
git checkout 8dcf53e06fd9f40182dd29e0a99aeb8fe8e5a94b
yarn
ember s
# error! (ember-cli crashes)

Inverse reproduction (fix?): Remove ember-cli-typescript: https://github.com/NullVoxPopuli/ember-play/pull/5/commits/689c0ee0777c6e57e9714f319f8f04bb8c356c63

  • Downside: no more type checking working in ember-cli terminal

Now about that bug. What did you expect to see?

This is a WIP PR / Library, but, I expect to still be able to run /tests while I iterate on implementation and not have to continually restart ec-ts whenever there is an error.

NullVoxPopuli avatar Jul 04 '21 14:07 NullVoxPopuli

I tried it again after working through the type errors, and it looks like the prepare command also doesn't work

NullVoxPopuli avatar Jul 05 '21 11:07 NullVoxPopuli

For what it's worth, our app & addons work with ember-source 3.27.5 & latest ember-cli-typescript. So I do not think it is a general issue, but probably some combination of another addon or so.

mydea avatar Jul 05 '21 13:07 mydea

We also have CI running against stable, beta, and canary as well as all supported LTS releases, and I'm using it in multiple addons which are on 3.27 as well. It'd be helpful if you can get to a minimal reproduction!

chriskrycho avatar Jul 05 '21 16:07 chriskrycho

Alrighty, I'll do some digging. Thanks!

NullVoxPopuli avatar Jul 05 '21 16:07 NullVoxPopuli

You didn't include this in the error report, but assuming this is the same as what you're describing in Discord, this log message is relevant:

Stack Trace and Error Report: /tmp/error.dump.f54b0c0bb56928ce98080855828d851b.log
internal/process/promises.js:194
        triggerUncaughtException(err, true /* fromPromise */);
        ^

Error: Typechecking failed
    at Class.postBuild (/home/me/Development/NullVoxPopuli/ember-play/node_modules/ember-cli-typescript/js/addon.js:73:19)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Promise.all (index 0)
    at async Builder.build (/home/me/Development/NullVoxPopuli/ember-play/node_modules/ember-cli/lib/models/builder.js:209:7)

That exception is us rejecting the promise we return from postBuild, which we do by design when noEmitOnError is enabled. This is how we fail the build for type errors, and hasn't changed since 2.0 iirc.

It's possible something has changed in ember-cli such that promise rejections from that hook aren't being handled, or the rejection handler isn't being immediately set. If it's the latter, we might be able to work around that by artifically delaying when we report a failure, but ultimately it seems like a rejected promise in postBuild shouldn't cause the whole process to shut down. When Node 15 was first released and unhandled rejections began being treated like uncaught exceptions, I remember this (or something similar) coming up briefly, but I'd thought that was taken care of pretty quickly on the CLI side.

dfreeman avatar Jul 06 '21 11:07 dfreeman

here is a reproduction: https://github.com/NullVoxPopuli/ec-typescript-repro-1439

all I did was add a file with const two: number = 'two';

NullVoxPopuli avatar Jul 11 '21 12:07 NullVoxPopuli

Log / error file

=================================================================================

ENV Summary:

  TIME: Sun Jul 11 2021 08:03:41 GMT-0400 (Eastern Daylight Time)
  TITLE: ember
  ARGV:
  - 🏠/.volta/tools/image/node/16.2.0/bin/node
  - /βœ‚οΈ/ec-typescript-repro-1439/node_modules/.bin/ember
  - s
  EXEC_PATH: 🏠/.volta/tools/image/node/16.2.0/bin/node
  TMPDIR: /tmp
  SHELL: /bin/bash
  PATH:
  - 🏠/.volta/tools/image/npm/7.7.5/bin
  - 🏠/.volta/tools/image/yarn/1.22.5/bin
  - 🏠/.volta/tools/image/node/16.2.0/bin
  - 🏠/.volta/bin
  - 🏠/.pythons/Python-3.6.3/bin
  - 🏠/.cargo/bin
  - 🏠/Applications
  - 🏠/apps/phantomjs/bin
  - 🏠/scripts/system-utils
  - 🏠/scripts/git
  - 🏠/scripts/rails
  - 🏠/scripts
  - 🏠/.volta/bin
  - /usr/local/sbin
  - /usr/local/bin
  - /usr/sbin
  - /usr/bin
  - /sbin
  - /bin
  - /usr/games
  - /usr/local/games
  - /snap/bin
  - 🏠/.dotnet/tools
  - 🏠/.dotnet/tools
  - 🏠/.fzf/bin
  PLATFORM: linux x64
  FREEMEM: 281653248
  TOTALMEM: 17388208128
  UPTIME: 131706.37
  LOADAVG: 1.59,0.61,0.31
  CPUS:
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  - Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
  ENDIANNESS: LE
  VERSIONS:
  - ares: 1.17.1
  - brotli: 1.0.9
  - cldr: 39.0
  - icu: 69.1
  - llhttp: 6.0.1
  - modules: 93
  - napi: 8
  - nghttp2: 1.42.0
  - nghttp3: 0.1.0-DEV
  - ngtcp2: 0.1.0-DEV
  - node: 16.2.0
  - openssl: 1.1.1k+quic
  - tz: 2021a
  - unicode: 13.0
  - uv: 1.41.0
  - v8: 9.0.257.25-node.16
  - zlib: 1.2.11

ERROR Summary:

  - broccoliBuilderErrorStack: [undefined]
  - code: [undefined]
  - codeFrame: [undefined]
  - errorMessage: Typechecking failed
  - errorType: [undefined]
  - location:
    - column: [undefined]
    - file: [undefined]
    - line: [undefined]
  - message: Typechecking failed
  - name: Error
  - nodeAnnotation: [undefined]
  - nodeName: [undefined]
  - originalErrorMessage: [undefined]
  - stack: Error: Typechecking failed
    at Class.postBuild (/βœ‚οΈ/ec-typescript-repro-1439/node_modules/ember-cli-typescript/js/addon.js:73:19)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Promise.all (index 0)
    at async Builder.build (/βœ‚οΈ/ec-typescript-repro-1439/node_modules/ember-cli/lib/models/builder.js:209:7)

=================================================================================


Tangentially, I made a script to make the paths in my error logs a little nicer, in case anyone is interested in doing that (like if you decided to use your full name as your computer's username without realizing how it affects paths in error logs πŸ™ƒ ) https://github.com/NullVoxPopuli/dotfiles/blob/75ad3987e4eaa550e7dfb70a37ffe2b756594bd9/home/scripts/unme

NullVoxPopuli avatar Jul 11 '21 13:07 NullVoxPopuli

Things I've tried so far

  • deleting the postBuild function in node_modules/ember-cli-typescript/js/addon.js
    • ember s
      • let's the build complete without crashing ember-cli
      • type error is still reported to the terminal
    • yarn prepack
      • errors (expected, because type error)
    • yarn postpack
      • succeeds (expected)

NullVoxPopuli avatar Jul 11 '21 14:07 NullVoxPopuli

I went hunting and it looks like the situation is pretty much what I was speculating above. I spun up fresh app with an in-repo addon that returns Promise.reject('uh oh') from postBuild() after each even-numbered (re)build.

Here's the output for an initial build and three subsequent rebuilds (so in total, success -> fail -> success -> fail):

[email protected], Node 12/16
$ ember serve

Build successful (3376ms) – Serving on http://localhost:7020/

Slowest Nodes (totalTime >= 5%)                                                                                             | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
BroccoliRollup (6)                                                                                                          | 693ms (115 ms)
Bundler (1)                                                                                                                 | 660ms
Babel: @ember/test-helpers (1)                                                                                              | 395ms
Package /assets/vendor.js (1)                                                                                               | 299ms
Babel: ember-source (5)                                                                                                     | 254ms (50 ms)
ember-auto-import-analyzer (4)                                                                                              | 216ms (54 ms)

file changed templates/application.hbs
file changed templates/application.hbs
uh oh

file changed templates/application.hbs

Build successful (232ms) – Serving on http://localhost:7020/

Slowest Nodes (totalTime >= 5%)                                                                                             | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Babel: ember-source (5)                                                                                                     | 33ms (6 ms)
ember.js (1)                                                                                                                | 30ms
BroccoliMergeTrees (22)                                                                                                     | 27ms (1 ms)
Funnel (60)                                                                                                                 | 22ms (0 ms)

file changed templates/application.hbs
uh oh
[email protected], Node 12
$ ember serve                                                                                                                                                                                                                 

Build successful (3573ms) – Serving on http://localhost:7020/

Slowest Nodes (totalTime >= 5%)                                                                                             | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Bundler (1)                                                                                                                 | 777ms
BroccoliRollup (6)                                                                                                          | 680ms (113 ms)
Babel: @ember/test-helpers (1)                                                                                              | 379ms
Package /assets/vendor.js (1)                                                                                               | 337ms
Babel: ember-source (5)                                                                                                     | 284ms (56 ms)
ember-auto-import-analyzer (4)                                                                                              | 207ms (51 ms)

file changed templates/application.hbs
(node:22890) UnhandledPromiseRejectionWarning: uh oh
(Use `node --trace-warnings ...` to show where the warning was created)
(node:22890) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:22890) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
file changed templates/application.hbs

Build successful (229ms) – Serving on http://localhost:7020/

Slowest Nodes (totalTime >= 5%)                                                                                             | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Babel: ember-source (5)                                                                                                     | 35ms (7 ms)
ember.js (1)                                                                                                                | 30ms
BroccoliMergeTrees (22)                                                                                                     | 27ms (1 ms)
Funnel (60)                                                                                                                 | 23ms (0 ms)

file changed templates/application.hbs
(node:22890) UnhandledPromiseRejectionWarning: uh oh
(node:22890) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 6)
[email protected], Node 16
$ ember serve                                                                                                                                                                                                                 WARNING: Node v16.4.2 is not tested against Ember CLI on your platform. We recommend that you use the most-recent "Active LTS" version of Node.js. See https://git.io/v7S5n for details.

Build successful (3616ms) – Serving on http://localhost:7020/

Slowest Nodes (totalTime >= 5%)                                                                                             | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
BroccoliRollup (6)                                                                                                          | 729ms (121 ms)
Bundler (1)                                                                                                                 | 726ms
Babel: @ember/test-helpers (1)                                                                                              | 444ms
Package /assets/vendor.js (1)                                                                                               | 268ms
Babel: ember-source (5)                                                                                                     | 258ms (51 ms)
ember-auto-import-analyzer (4)                                                                                              | 221ms (55 ms)

file changed templates/application.hbs
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "uh oh".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

Prior to 3.15, the CLI treated promise rejections in postBuild as failing the build, so in both older and newer versions of Node, everything works as expected.

Starting in 3.15, a promise returned from postBuild doesn't get .catch()ed, meaning the rejection goes unhandled. In older versions of Node, this emits a warning (and seemingly still does fail the build, which is interesting), but in more recent Node versions, that unhandled rejection warning terminates the process.

Like I said above, given that ember-cli does wait for postBuild promises (i.e. it doesn't just ignore the postBuild return value), it seems like a bug there that the rejection goes unhandled, and I think the behavior prior to 3.15 was correct.

dfreeman avatar Jul 12 '21 12:07 dfreeman

So is this something that needs to be fixed here or in ember-cli?

NullVoxPopuli avatar Jul 12 '21 12:07 NullVoxPopuli

This would have to be a change in ember-cli.

dfreeman avatar Jul 12 '21 12:07 dfreeman

it seems this is still broken.

would it not be easier to flip noEmitOnError to false until ember-cli is fixed?

Today, everyone starting a new project will not be able to successfully run ember s if there exists a type error.

NullVoxPopuli avatar Aug 27 '21 12:08 NullVoxPopuli

I have this problem and noEmitOnError is true.

@dfreeman's comment above suggests that this is intentional when noEmitOnError is true which feels like exact opposite of what that flag means...

which we do by design when noEmitOnError is enabled.

runspired avatar Mar 31 '22 17:03 runspired

I think we got the confusion sorted out in Discord, but for anyone else reading along in this thread: noEmitOnError is a TypeScript configuration option (not something we invented!) that means "do not emit transpiled code when there's a type error."

dfreeman avatar Apr 01 '22 07:04 dfreeman

Since the tsconfig from the blueprint still has noEmitOnError: true, and this (with current ember-cli) still leads to the build crashing whenever there is a type error, would it make sense to set this to false in the blueprint? IMHO as it is now, it is not really an acceptable dev experience to have noEmitOnError: true (I understand why it would be nice to have it, but as long as ember-cli simply kills the server it is not really useful at all).

Also related sidenote, I think there is part of the comment missing there: https://github.com/typed-ember/ember-cli-typescript/blob/master/blueprint-files/ember-cli-typescript/tsconfig.json#L43 it simply ends on "when" ;)

mydea avatar May 09 '22 13:05 mydea

I think we’ve stated our position clearly enough before, but I’m going to state it one more time for the record and then lock the thread:

Disabling that feature in ember-cli-typescript would break many existing users' assumptions, and the bug is not here but upstream. We are not changing the behavior of ember-cli-typescript on this front.

For extra clarity here: the main thing that adding ember-cli-typescript to your project does is add type checking integration into your build. If you don’t want that, then you can just opt into the corresponding babel config and run tsc manually yourself!

chriskrycho avatar May 10 '22 19:05 chriskrycho

Added this to the above, but wanted to add it as a comment so folks following via email etc. see it:

For extra clarity here: the main thing that adding ember-cli-typescript to your project does is add type checking integration into your build. If you don’t want that, then you can just opt into the corresponding babel config and run tsc manually yourself!

chriskrycho avatar May 10 '22 19:05 chriskrycho