cypress: `ERR_LOADER_CHAIN_INCOMPLETE` in CI, works locally in a Dev Container

Current behavior

Stacktrace:

Error [ERR_LOADER_CHAIN_INCOMPLETE]: "file:///root/.cache/Cypress/10.3.0/Cypress/resources/app/node_modules/ts-node/esm/transpile-only.mjs 'resolve'" did not call the next hook in its chain and did not explicitly signal a short circuit. If this is intentional, include `shortCircuit: true` in the hook's return.
    at new NodeError (node:internal/errors:387:5)
    at ESMLoader.resolve (node:internal/modules/esm/loader:860:13)
    at async ESMLoader.getModuleJob (node:internal/modules/esm/loader:439:7)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:541:24)
    at async loadESM (node:internal/process/esm_loader:83:5)
    at async handleMainPromise (node:internal/modules/run_main:65:12) {
  code: 'ERR_LOADER_CHAIN_INCOMPLETE'

I noticed this too:

libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[1395:0714/145055.804094:ERROR:sandbox_linux.cc(377)] InitializeSandbox() called with multiple threads in process gpu-process.
[1395:0714/145055.807765:ERROR:gpu_memory_buffer_support_x11.cc(44)] dri3 extension not supported.

But otherwise didn’t find any useful search results when searching for “ERR_LOADER_CHAIN_INCOMPLETE” so I’m going to file this so I can answer it when I figure it out 😃

Desired behavior

Don’t short circuit on resolve.

Test code to reproduce

Not sure yet… I’m going to start by trying v10.2.* because it only recently stopped working in CI, so maybe it broke with v10.2.*.

I am using this .gitlab-ci.yml:

{
  "image": "mcr.microsoft.com/playwright:latest",
  "before_script": [
    "# Node.js v18",
    "apt-get remove nodejs -y",
    "apt-get update",
    "apt-get install -y curl",
    "curl -fsSL https://deb.nodesource.com/setup_18.x | bash -",
    "apt-get install -y nodejs",
    "npm install",
    "# SSH",
    "eval $(ssh-agent -s)",
    "echo \"$SSH_PRIVATE_KEY\" | ssh-add -",
    "mkdir -p ~/.ssh",
    "chmod 700 ~/.ssh",
    "ssh-keyscan host.docker.internal >> ~/.ssh/known_hosts",
    "chmod 644 ~/.ssh/known_hosts"
  ],
  "stages": [
    "build",
    "confidence-check"
  ],
  "pages": {
    "stage": "build",
    "script": [
      "npm run cypress",
      "npm run cypress-static",
      "rm -rf public",
      "mv out public"
    ],
    "artifacts": {
      "paths": [
        "public"
      ]
    },
    "only": [
      "main"
    ]
  },
  "e2e": {
    "stage": "confidence-check",
    "script": [
      "npx cypress run --config baseUrl=$CI_PAGES_URL"
    ],
    "only": [
      "main"
    ]
  }
}

and here are the relevant scripts from my package.json, which are a bit gnarly:

{
  "scripts": {
    "cypress": "CODE=0 ; (npm start & { npx cypress run ; CODE=$? ; kill -INT $(jobs -p) ; }) ; (exit $CODE)",
    "cypress-static": "CODE=0 ; npm run build && (npm run serve & { npx cypress run --config baseUrl=http://localhost:8080/ ; CODE=$? ; kill -INT $(jobs -p) ; }) ; (exit $CODE)",
    "build": "next build && npm run postbuild && next export && npm run postexport",
    "postbuild": "node --experimental-specifier-resolution=node --loader=ts-node/esm scripts/postbuild.ts",
    "postexport": "node --experimental-specifier-resolution=node --loader=ts-node/esm scripts/postexport.ts",
    "serve": "npx http-server . -c-1",
    "start": "node --experimental-specifier-resolution=node --loader=ts-node/esm server.ts"
  }
}

and my cypress.config.ts, even though it’s pretty plain:

import { defineConfig } from "cypress";

export default defineConfig({
	"e2e": {
		"baseUrl": "http://localhost:3000/",
		"setupNodeEvents": function(on, config) {
			// Implement node event listeners here
		}
	},
	"video": false,
	"viewportHeight": 1080,
	"viewportWidth": 1920
});

Cypress Version

v10.3.0

Other

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 4
  • Comments: 29 (9 by maintainers)

Most upvoted comments

@isgj Same issue here. Cypress v10 is broken on current Node LTS.

Node 16.17.0 also introduced the same Experimental ESM Loader Hooks API as 18.6.0. Reverting back to previous LTS 16.15.1 works for now. 🎉

I think it may be related to https://github.com/TypeStrong/ts-node/issues/1714

I have the same error after updating nodejs to 18.6.0

@SchulteMarkus I get this error with 10.9

image

npm -v

I confirm it’s a node version issue. I’m using now nvm with a node@16.15.1 an it works well now

Right, yes, my bad – I’ve been using this feature for so long I’d forgotten it’s still experimental. Thanks for pointing that out. I’ve updated my comment to clarify (but left original one there, too, for context).

Either way, @cspotcode’s great ts-node library fixed the issue almost immediately and now we’ve updated to use the latest version, everything should work just fine here, too.

Thanks for making ts-node - I (personally, and at Cypress) use it every day and it works great 💯

@jsolly https://github.com/cypress-io/cypress/pull/23637 should fix this. In the meantime you could install Node.js 16.16, and that should work, too. Node.js 16.17 had a breaking change (surprise minor version breaking change).

Edit: see below - worth nothing that my above comment isn’t accurate - while this did catch us off guard, es modules in Node.js is still experimental, so there is not commitment to server.

18.6.0 introduced loader chaining, that error code, and a new requirement which loaders must implement in some situations to avoid it. So if any loaders are being used, and if they’re out-of-date, they may trigger that error.

I took another look and was able to recreate the error. @brianjenkins94 thanks for bearing with me. This appears to work on node v18.2.0 but does not work on node 18.6.0

Windows:

image

Linux (Dev Container):

image

Can someone please create a ts-node issue to discuss? It’s easier for me to keep track of those.

The short-circuit thing is potentially misleading, because often loaders should short-circuit, but node’s loaders API demands that we signal the intent via a flag in the return value. This error happens when that intention is not signaled. It’s complicated.