Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined by "exports"
Asked Answered
F

4

57

I got this error when using uuidv4.

Failure: Package subpath './v4' is not defined by "exports" in C:\Users\mycomp\Desktop\Programming\Javascript\Serverless\Serverless Framework\node_modules\uuid\package.json
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined by "exports" in C:\Users\mycomp\Desktop\Programming\Javascript\Serverless\Serverless Framework\node_modules\uuid\package.json

I already installed uuid and require it in my code

const uuidv4 = require('uuid/v4');

Here's the package.json

"dependencies": {
  "aws-sdk": "^2.702.0",
  "moment": "^2.27.0",
  "serverless-offline": "^6.4.0",
  "underscore": "^1.10.2",
  "uuid": "^8.1.0"
}
Floriculture answered 24/6, 2020 at 7:0 Comment(0)
I
85

ECMAScript Module syntax:

import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

CommonJS syntax:

const { v4: uuidv4 } = require('uuid');
uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'
Indiscerptible answered 24/6, 2020 at 12:29 Comment(3)
can you provide some context here? how is this solving the issue?Goop
Same, this exact code is giving the errorOtherworldly
Version 7 of the uuid package deprecated deep imports require('uuid/v4'), and version 8 removed them. That's why the code in the question doesn't work, since it uses version 8 of the package, but tries to import it using require('uuid/v4'). This answer solves the problem by not using deep imports.Devilkin
C
11

Another option

const uuid = require('uuid');
uuid.v4(); // "c438f870-f2b7-4b2c-a1c3-83bd88bb1d79"
Caulis answered 6/10, 2021 at 3:59 Comment(0)
T
7

We had the same error with v1 uuid module (v8.3.2).

Solved this, adding following entry to exports section of installed uuid package.json(inside your node_modules):

"./v1": "./dist/v1.js"

Full export section of my projects' node_modules/uuid/package.json:

  "exports": {
    ".": {
      "node": {
        "module": "./dist/esm-node/index.js",
        "require": "./dist/index.js",
        "import": "./wrapper.mjs"
      },
      "default": "./dist/esm-browser/index.js"
    },
    "./package.json": "./package.json",
    "./v1": "./dist/v1.js"
  },

The problem remaining i now need to keep this modification across dist installs... :/

This could be fixed with a patch on uuid source itself?

EDIT: Didn't require the module in our own source. It is a dependency of jest (via some jest reporting sub-pkg).

EDIT: Alternatively, rolling back to uuid dep to v7.0.3 may fix this issue too, see comment below.

Tonyatonye answered 14/10, 2021 at 1:46 Comment(11)
I'd recommend submitting this as PR to the uuid git repo. This error is still occurring on the latest version (v8.3.2). I dropped all the way back to the v7.0.3 build to be able to require the module correctly.Rathe
thanks for figuring out which build to rollback to to fix :)Tonyatonye
@Rathe can you vote +1 my answer anyhow? :) also, i am not involved into uuid repo. atm i am reluctant to open a PR as i am not sure if maintainers will consider this a fix itfp. they might have their reasons to have broken things? you know what i mean? :) furthermore, this change only fixes v1 ...Tonyatonye
created a PR github.com/uuidjs/uuid/pull/584Tonyatonye
Why do you insist on using deep require syntax? Deep requires have intentionally been deprecated in [email protected] and removed [email protected], upgrade instructions are given in the CHANGELOG, more context in github.com/uuidjs/uuid/pull/361#issuecomment-585397739. Does the accepted answer above work for you?Delaryd
@Delaryd unfortunately the accepted answer is not applicable in our case, because we are not importing the packet ourselves. it is used in our build tooling and as the newer version is loaded by legacy direct deps on our side, the mentioned error appears. other than in a sub-dep of jest (jest-reporter) also in webpack worker-loader plugin. but these are only examples. it shows dropping support for the legacy way of importing the module on uuid project side has potential effects on (n-th degree) consumers.Tonyatonye
This problem is hard to diagnose without a reproduction case. Please feel free to report the issue at github.com/uuidjs/uuid providing a minimal reproducible example (stackoverflow.com/help/minimal-reproducible-example) so we can address it.Delaryd
Yes, well, we have only solved it with enforcing usage of an older uuid dep all over, which does work nicely. All I would want to suggest to uuid maitainers is to keep backward compatible with legacy distro modes, instead of insisting on idealistical concepts.Tonyatonye
@Tonyatonye I think that the correct approach here is to fix it in the package that is importing uuid wrong. That package was intended to use an older version, and even if the deep require were added back to 8.x, there could be other subtle differences as well. Can you please run npm ls uuid and post a list of which of your dependencies depends on uuid?Devilkin
yes that is correct in theory - but in practice i wouldn't possibly fork such a dependency and the dependent package where i would have to make it point to the first (or n other forks needed depending on the depth of the dependency in the tree :D)Tonyatonye
Don't think this is feasible when time to ship to production comes.Nabalas
I
0

docs:

https://nodejs.org/api/esm.html

Like in CommonJS, module files within packages can be accessed by appending a path to the package name unless the package's package.json contains an "exports" field, in which case files within packages can only be accessed via the paths defined in "exports".

https://nodejs.org/api/packages.html#main-entry-point-export

When the "exports" field is defined, all subpaths of the package are encapsulated and no longer available to importers. For example, require('pkg/subpath.js') throws an ERR_PACKAGE_PATH_NOT_EXPORTED error.

This encapsulation of exports provides more reliable guarantees about package interfaces for tools and when handling semver upgrades for a package.

It is not a strong encapsulation since a direct require of any absolute subpath of the package such as require('/path/to/node_modules/pkg/subpath.js') will still load subpath.js.

you can get the absolute path of node_modules/pkg with something like

function get_absolute_module_path(name) {
  // this can throw MODULE_NOT_FOUND
  const main_export = require.resolve(name);
  const suffix = `/node_modules/${name}/`;
  const idx = main_export.lastIndexOf(suffix);
  if (idx == -1) {
    throw new Error(`failed to parse module path from main export path ${main_export}`);
  }
  const end = idx + suffix.length - 1;
  return main_export.slice(0, end);
}

console.log(get_absolute_module_path("pkg"));

different package managers will produce different paths, for example

npm:
/tmp/tmp.OPv0pmip4T/node_modules/cowsay

pnpm:
/tmp/tmp.ls6MykLOOC/node_modules/.pnpm/[email protected]/node_modules/cowsay
Incidentally answered 18/10, 2022 at 7:13 Comment(4)
What's the solution for 3rd party packages?Josselyn
what are "3rd party packages"?Incidentally
This issue affected a package I wasn't importing directly, so no control over its codebase. That is 3rd party. Anyway, nvm. I skipped the initialization command for vue apollo and have all but abandoned the project that required itJosselyn
"no control over its codebase" sounds like a use-case for patch-package (but different package managers will install transitive dependencies in different paths)Incidentally

© 2022 - 2024 — McMap. All rights reserved.