Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. #422

Closed
trcarden opened this issue Jun 29, 2019 · 5 comments
Closed

Comments

@trcarden
Copy link

trcarden commented Jun 29, 2019

  • Operating System: OSX 10.14.5
  • Node Version: v11.15.0
  • NPM Version: 6.7.0
  • webpack Version: 4.32.2
  • karma-webpack Version: 4.0.2

Expected Behavior

When I run yarn run karma start config/karma.conf.js --single-run it compiles the code and run tests

Actual Behavior

When i run yarn run karma start config/karma.conf.js --single-run it errors out on path receiving a undefined value

root@0820a953acc0:~/titan# yarn run karma start config/karma.conf.js --single-run --pattern=spec/javascript/lib/store/event_spec.js
yarn run v1.16.0
$ /root/titan/node_modules/.bin/karma start config/karma.conf.js --single-run --pattern=spec/javascript/lib/store/event_spec.js
[]
ℹ 「wdm」: Hash: 9d2c943b68425fd58dd0
Version: webpack 4.32.2
Time: 82ms
Built at: 06/29/2019 6:55:15 PM
        Asset      Size  Chunks             Chunk Names
manifest.json  23 bytes          [emitted]
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...
29 06 2019 18:55:15.822:ERROR [karma-server]: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
    at validateString (internal/validators.js:125:11)
    at Object.join (path.js:1037:7)
    at Plugin.<anonymous> (/root/titan/node_modules/karma-webpack/dist/karma-webpack.js:318:70)
    at Plugin.readFile (/root/titan/node_modules/karma-webpack/dist/karma-webpack.js:334:5)
    at /root/titan/node_modules/karma-webpack/dist/karma-webpack.js:353:19
    at nextPreprocessor (/root/titan/node_modules/karma/lib/preprocessor.js:32:26)
    at /root/titan/node_modules/karma/lib/preprocessor.js:121:9
    at module.exports (/root/titan/node_modules/isbinaryfile/index.js:29:12)
    at readFileCallback (/root/titan/node_modules/karma/lib/preprocessor.js:87:7)
    at /root/titan/node_modules/graceful-fs/graceful-fs.js:90:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:54:3)
error Command failed with exit code 1.

Workaround

I found that if I simply return after notifyKarmaAboutChanges (effectively continuing the blocking until the next run of the compiler) then the issue no longer occurs.

Other People stuck with similar issues:

Trace of the problem

As you can plainly see from the backtrace the issue is caused by a undefined being passed to path.join. The line in question is

const fileContents = middleware.fileSystem.readFileSync(path.join(os.tmpdir(), '_karma_webpack_', this.outputs.get(file)));

and this.outputs (last parameter in call) is a blank Map when it fails.

I traced through the code a few times and found that only when this fails it calls notifyKarmaAboutChanges in done() callback for the webpacker compile hook.

However there seems to be a few issues with this

  1. notifyKarmaAboutChanges effectively triggers a rebuild but the isBlocked flag is set to false at the end of done, since that is a module level flag it when the compiler goes through a second time nothing will be blocked.
  2. When notifyKarmaAboutChanges is called it effectively starts compilation twice (that seems very funky to me, why does the done handler have a hook to rerun the compilation system?) -- You can see this via the trace above where the output clearly dumps
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...

Code

ConfigObject {
  mode: 'production',
  output: {
    filename: 'js/[name]-[contenthash].js',
    chunkFilename: 'js/[name]-[contenthash].chunk.js',
    hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
    path: 'path/to/public/packs',
    publicPath: '/packs/'
  },
  resolve: {
    extensions: [
      '.mjs',
      '.js',
      '.sass',
      '.scss',
      '.css',
      '.module.sass',
      '.module.scss',
      '.module.css',
      '.png',
      '.svg',
      '.gif',
      '.jpeg',
      '.jpg'
    ],
    plugins: [ [Object] ],
    modules: [
      'path/to/app/javascript',
      'node_modules'
    ]
  },
  resolveLoader: { modules: [ 'node_modules' ], plugins: [ [Object] ] },
  node: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  },
  optimization: { splitChunks: { chunks: 'all', name: false }, runtimeChunk: true },
  module: {
    strictExportPresence: true,
    rules: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ]
  },
  plugins: [
    EnvironmentPlugin { keys: [Array], defaultValues: [Object] },
    CaseSensitivePathsPlugin {
      options: {},
      pathCache: {},
      fsOperations: 0,
      primed: false
    },
    MiniCssExtractPlugin { options: [Object] },
    WebpackAssetsManifest {
      hooks: [Object],
      options: [Object],
      assets: [Object: null prototype] {},
      assetNames: Map {},
      currentAsset: null,
      compiler: null,
      stats: null,
      hmrRegex: null,
      [Symbol(isMerging)]: false
    }
  ],
  devtool: 'none'
}

How Do We Reproduce?

Its intermittent but simply running the test suite with a single large test file gives me about a 70-80% hit rate.

@jpzwarte
Copy link

jpzwarte commented Jun 4, 2020

The code to wait for the file is already present in the catch handler. Easiest to just expand on that:

      try {
        const fileContents = middleware.fileSystem.readFileSync(path.join(os.tmpdir(), '_karma_webpack_', this.outputs.get(file)));
        callback(null, fileContents);
      } catch (e) {
        // If this is an error from `readFileSync` method, wait for the next tick.
        // Credit #69 @mewdriller
        if (e.code === 'ENOENT' || !this.outputs.get(file)) {
          // eslint-disable-line quotes
          this.waiting = [process.nextTick.bind(process, this.readFile.bind(this, file, callback))]; // throw otherwise
        } else {
          callback(e);
        }
      }

@lobosan
Copy link

lobosan commented Aug 9, 2020

Any solution for this? I'm stuck with this issue and I cannot run tests :(

@sbrady
Copy link

sbrady commented Aug 17, 2020

Here is the worst monkey patch ever

const karmaWebpack = require('karma-webpack')
const original = karmaWebpack.webpackPlugin[1].prototype.readFile
karmaWebpack.webpackPlugin[1].prototype.readFile = function (file, callback) {
    let cb = function () {
        if (arguments[0] && arguments[0].code === 'ERR_INVALID_ARG_TYPE') {
            console.log('errors!!!!! waiting')
            this.waiting = [process.nextTick.bind(process, this.readFile.bind(this, file, callback))]; // throw otherwise
        }else{
            return callback(...arguments)
        }
    }.bind(this)

    original.call(this, file, cb)
}

@dlandtwing
Copy link

Is there any chance of having this fixed soon? We're running into this issue in about 50% of our test runs.

@codymikol
Copy link
Owner

Hey, the reason this was failing is because you're specifying a filename and karma-webpack relies on the default filename to figure out how to map the webpack bundles to the karma files. I just merged a fix into next that will automatically correct this and we will cut a new version soon. For now if you just remove filename: 'js/[name]-[contenthash].js' from your configuration it will work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants