Skip to content

[BUG] npm ci fails with git based dependencies #1214

Closed
@LoganBarnett

Description

@LoganBarnett

What / Why

When invoking npm ci, the command fails with premature close and little else.

When

  • invoking npm ci and a git dependency with a prepare script is included.

Where

  • Our internal Jenkins servers.
  • Internal packages are consumed over git. Public packages are fine.

How

Current Behavior

When invoking npm ci, our org sees this error:

[2020-04-15T18:53:51.235Z] + npm ci
[2020-04-15T18:53:56.677Z] npm ERR! premature close
[2020-04-15T18:54:04.979Z] 
[2020-04-15T18:54:04.979Z] npm ERR! A complete log of this run can be found in:
[2020-04-15T18:54:04.979Z] npm ERR!     /home/jenkins/.npm/_logs/2020-04-15T18_53_56_371Z-debug.log

Steps to Reproduce

This is sticky, but here's my best shot:

  1. Have a repository that consumes another via git.
  2. The consumed repository has a prepare script. Doesn't matter what's in it.
  3. Have a sufficient number of CA certificates? I'm less confident here.
  4. Run npm ci.
  5. Observe. Weep.

Expected Behavior

npm ci should succeed, given the prepare script and all of other packages are healthy.

Who

My workplace, but I am happy to be the primary contact.

References

  1. Perhaps coincidentally related to fd0a802

Other notes

I spent some time on this and it's possible more than one bug will fall out of it. The logging here doesn't seem useful (a bug of its own), but fixing the logging won't get down to the root cause. I intend to track the root cause in this ticket, and may file another for the logging issue.

When we dial up the logging to silly, we more or less see the same thing. We did prune our dependencies until we found the foremost ones involved. They are internal git based dependencies. I can furnish the verbose logs if desired, but I will omit them from the initial report since I believe they will only add noise. The last log seen from the problematic packages is prepareGitDep.

prepareGitDep <repo-name>@git+ssh://git@<repo-url>.git#<commit-hash>: installing devDeps and running prepare script.

There are a lot of other logs between this and other things - I assume this is due to the asynchronous manner of package installation.

The git dependency in question has a prepare script declared in its package.json. If I remove prepare, everything works. If I replace the prepare script with something rudimentary such as "echo 'hi'", "true", or even "" I still get the error above.

This may be noise: We noticed this in 6.14.4 from 6.13.4 - when our Node version transitioned from 12.16.2 to 12.16.3. I was able to walk commits and found the problem reliably appeared at this commit. All it does is points cacache to the _cacache subdirectory, whereas beforehand there was no subdirectory. Later we were able to reproduce the error in 6.13.4, so I think the _cacache change might exacerbate the issue, but is not the direct cause.

I made some direct edits to my local copy of npm and found that if, in pack.js, I change cliArgs to just be [] that everything Just Works(tm). I don't believe this is a sustainable fix though. Further debugged revealed the issue to be E2BIG - an error that a single command line argument exceeded the kernel's restriction. Ours is set to 2097152, which I understand to be the Linux default - and is restricted by the kernel's page size. You can view your own with getconf ARG_MAX at your terminal. I inspected the cliArgs and found that ca was set to the cert data of every certificate on the machine. I perused these and found a standard assortment of CA certs, intermediate certificates, etc. Our organization's internal certificates were included. I assume but have not yet verified that this is simply reading from the local machine's OpenSSL's certificate list - I know that we don't set it explicitly. .npmrc has only cafile=/etc/pki/tls/certs/ca-bundle.crt in relation to certificates. The build machine where this behavior is observed is running CentOS 7.7.1908. Most of us use Macs at the workplace, and we do not see this error on them with the same node/npm versions.

Since this restriction applies to a single argument, I chopped up ca into multiple ca[] arguments. This seems to work for pack.js but it kicks the can down the road. I suspect that other parts of npm need a similar treatment, but the processes have either become too opaque for me to trace much further, or I my simian mind is too simple and unfamiliar with npm innards.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugthing that needs fixingRelease 6.xwork is associated with a specific npm 6 release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions