Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot get past "Must module.exports a string."

See original GitHub issue
  • babel-plugin-codegen version: 3.0.0
  • node version: 10.15.0
  • npm (or yarn) version: yarn 1.13.0
  • babel: 7.4.5
  • babel-plugin-macros: 2.5.1 (required by another dep)

Relevant code or config

// my.js
codegen`module.exports = ''`;

// babel.config.js
module.exports = {
  presets: [
        targets: {
          browsers: [
            'last 2 versions',
            'ie 11',
        useBuiltIns: 'usage',
        corejs: 2,
  plugins: [

What you did:

Try to compile my.js

What happened:

codegen: Must module.exports a string.

      at getReplacement (node_modules/babel-plugin-codegen/dist/helpers.js:43:11)
      at replace (node_modules/babel-plugin-codegen/dist/helpers.js:69:21)
      at asFunction (node_modules/babel-plugin-codegen/dist/replace.js:57:5)
      at asIdentifier (node_modules/babel-plugin-codegen/dist/replace.js:127:22)
      at PluginPass.Identifier (node_modules/babel-plugin-codegen/dist/index.js:37:11)
      at newFn (node_modules/@babel/traverse/lib/visitors.js:193:21)
      at NodePath._call (node_modules/@babel/traverse/lib/path/context.js:53:20)
      at (node_modules/@babel/traverse/lib/path/context.js:40:17)
      at NodePath.visit (node_modules/@babel/traverse/lib/path/context.js:88:12)
      at TraversalContext.visitQueue (node_modules/@babel/traverse/lib/context.js:118:16)

Reproduction repository:

Problem description:

I cannot seem to get past the Must module.exports a string. I’ve tried using escaped backticks, double quotes and single quotes, joining arrays, concatenating strings some other way (e.g., with + operator), etc.

What am I doing wrong?

Suggested solution:


Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:2
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

rikonorcommented, Jul 9, 2020

Confirming this is still an issue.

That said, it can be circumvented by invoking codegen directly instead of using a tagged template:

# Instead of
codegen`module.exports = ...`

# do
codegen(`module.exports = ...`)
Fi2zzcommented, Mar 23, 2020

this issue can be reproduced when use with “@babel/preset-env”: see error stacks below

Error: ~/babel-demo/src/index.js: codegen: Must module.exports a string.
    at getReplacement (~/babel-demo/codegen/helpers.js:46:11)
    at replace (~/babel-demo/codegen/helpers.js:67:23)
    at asFunction (~/babel-demo/codegen/replace.js:144:5)
    at asIdentifier (~/babel-demo/codegen/replace.js:67:18)
    at PluginPass.Identifier (~/babel-demo/codegen/index.js:26:11)
    at newFn (~/babel-demo/node_modules/@babel/traverse/lib/visitors.js:179:21)
    at NodePath._call (~/babel-demo/node_modules/@babel/traverse/lib/path/context.js:55:20)
    at (~/babel-demo/node_modules/@babel/traverse/lib/path/context.js:42:17)
    at NodePath.visit (~/babel-demo/node_modules/@babel/traverse/lib/path/context.js:90:31)
    at TraversalContext.visitQueue (~/babel-demo/node_modules/@babel/traverse/lib/context.js:112:16) {

this line get the value with undefined:

const code = argumentsPaths[0].evaluate().value;

 function asFunction(path, fileOpts) {
    const argumentsPaths = path.get("arguments");
    // variable code  is undefined, 
    const code = argumentsPaths[0].evaluate().value;
        path: argumentsPaths[0].parentPath,
function getReplacement({ code, fileOpts, args = [] }, babel) {
  let module = requireFromString(code, fileOpts.filename);
  // If a function is epxorted, call it with args
  if (typeof module === "function") {
    module = module(...args);
  } else if (args.length) {
    throw new Error(
      `codegen module (${p.relative(
      )}) cannot accept arguments because it does not export a function. You passed the arguments: ${args.join(
        ", "

  // Convert whatever we got now (hopefully a string) into AST form
  if (typeof module !== "string") {
    // console.log(typeof module);
    throw new Error("codegen: Must module.exports a string.");

  return babel.template(module, {
    preserveComments: true,
    placeholderPattern: false,
    sourceType: "module"

seems @babel/plugin-transform-template-literals caused this issue, i have tested them one by one and combinations;


const pluginOfPresetEnv =[];
for(let key of transformations .keys()){
  //pluginOfPresetEnv [
    //   'transform-template-literals',
    //   'transform-literals',
    //   'transform-function-name',
    //   'transform-arrow-functions',
    //   'transform-block-scoped-functions',
    //   'transform-classes',
    //   'transform-object-super',
    //   'transform-shorthand-properties',
    //   'transform-duplicate-keys',
    //   'transform-computed-properties',
    //   'transform-for-of',
    //   'transform-sticky-regex',
    //   'transform-dotall-regex',
    //   'transform-unicode-regex',
    //   'transform-spread',
    //   'transform-parameters',
    //   'transform-destructuring',
    //   'transform-block-scoping',
    //   'transform-typeof-symbol',
    //   'transform-new-target',
    //   'transform-regenerator',
    //   'transform-exponentiation-operator',
    //   'transform-async-to-generator',
    //   'proposal-async-generator-functions',
    //   'proposal-object-rest-spread',
    //   'proposal-unicode-property-regex',
    //   'proposal-json-strings',
    //   'proposal-optional-catch-binding'
  // ]

  let pluginOfPresetEnvArray =[

        // 'transform-template-literals',


transformations.forEach(pluginName => {
  const config  ={ spec,loose, useBuiltIns: pluginUseBuiltIns}
  plugins.push([getPlugin(pluginName), config])
const regenerator = transformations.has("transform-regenerator");

here is the key codes :

after this step, the codegen function visitor dead

Read more comments on GitHub >

github_iconTop Results From Across the Web

javascript - Why can module.exports hold a String object and a ...
When I assign module. exports to a String literal object, it cannot hold any other properties and hence the error when we try...
Read more >
Node Module Exports Explained - freeCodeCamp
This is a common module exports mistake that people who are starting out with Node.js often make. They assign exports to a new...
Read more >
Understanding module.exports and exports in Node.js
It doesn't have to be the same as the original variable name. Variations in Syntax. I should also mention that it's possible to...
Read more >
Module Methods - webpack
The require label can occur before a string. The dependency must export values with the export label. CommonJS or AMD modules cannot be...
Read more >
Errors | Node.js v19.3.0 Documentation
To get the string representation of the error code, use util. ... private internal modules that are not exported cannot be imported through...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Post

No results found

github_iconTop Related Hashnode Post

No results found