cuid2: TypeError: Expected input type is Uint8Array (got object)

Been trying to upgrade to cuid2 from cuid on-off for a while now but never been able to solve this issue. Hoping maintainers or community can help.

I installed with the following:

yarn remove cuid
yarn add @paralleldrive/cuid2

And my diffs are essentially

- import cuid from "cuid"
+ import cuid2 from "@paralleldrive/cuid2"
- cuid()
+ cuid2.createId()

But I’m always seeing the error:

TypeError: Expected input type is Uint8Array (got object)

> 1 | import cuid2 from "@paralleldrive/cuid2"

Same with:

TypeError: Expected input type is Uint8Array (got object)

> 1 | import { createId } from "@paralleldrive/cuid2"

Only seems to be a problem on my web package, my api is not complaining.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 19

Most upvoted comments

JSDOM environment in Jest

This seems to be related to the use of jsdom as it builds global object which doesn’t match the one provided by Node.js. There is a known issue in Jest when jsdom environment is used and results of new TextEncoder().encode() and new Uint8Array() are different, refer to https://github.com/jestjs/jest/issues/9983.

The easy fix for the example provided by @AlaricWhitney would be to use custom environment which overwrites Uint8Array provided by jsdom:

  1. Install jest-environment-jsdom. Make sure to use the same version as your jest (in cuid2-issue example it was v27), ref. https://stackoverflow.com/a/72124554
❯ npm i jest-environment-jsdom@27
  1. Create jsdom-env.js file in the root
const JSDOMEnvironmentBase = require('jest-environment-jsdom');

Object.defineProperty(exports, '__esModule', {
    value: true
});

class JSDOMEnvironment extends JSDOMEnvironmentBase {
    constructor(...args) {
        const { global } = super(...args);

        global.Uint8Array = Uint8Array;
    }
}

exports.default = JSDOMEnvironment;
exports.TestEnvironment = JSDOMEnvironment;
  1. Update scripts to use the custom environment:
{
    // ...
    "scripts": {
        // ...
        "test": "react-scripts test --env=./jsdom-env.js",
        // ...
    },
}

P.S. Change will make tests in the example fail, since expectations were not updated to match results from createId.

JSDOM lacks features

Also it is known that jsdom doesn’t support TextEncoder and TextDecoder, refer https://github.com/jsdom/jsdom/issues/2524. The workaround would be similar, see this comment.


The bottom line is that when Unit Tests are executed via Jest, features like Uint8Array/TextEncoder/TextDecoder may be available in jsdom environment but will produce results different from those expected in Node.js or browser. It might be resolved by jsdom at some point, but there is no clear ETA on the issue. I personally don’t think it’s on cuid2 to adjust and use something else, but owner of the package may fill differently 🙃

@AlaricWhitney, @ericelliott I have validated that this works, hopefully it works for you too.

jest.config.mjs

const config = {
  ...
  // testEnvironment: 'jest-environment-jsdom',
  testEnvironment: './jest-environment-jsdom.js', // had to extend; see https://github.com/jsdom/jsdom/issues/2524
}

jest-environment-jsdom.js

const { TextEncoder, TextDecoder } = require('util')
const { default: $JSDOMEnvironment, TestEnvironment } = require('jest-environment-jsdom')

Object.defineProperty(exports, '__esModule', {
  value: true,
})

class JSDOMEnvironment extends $JSDOMEnvironment {
  constructor(...args) {
    const { global } = super(...args)
    global.TextEncoder = TextEncoder
    global.TextDecoder = TextDecoder
    global.Uint8Array = Uint8Array
  }
}

exports.default = JSDOMEnvironment
exports.TestEnvironment = TestEnvironment === $JSDOMEnvironment ? JSDOMEnvironment : TestEnvironment

This was a frustrating issue…

Since it doesn’t look like this is something we can easily fix with a code change, I have updated the Readme Troubleshooting section.