parcel-bundler/parcel · error · Error

"${exportName}" in "${src}" is not a function.

Error message

"${exportName}" in "${src}" is not a function.

What it means

Thrown from the SWC macro callback right before mod[exportName].apply(ctx, args) when typeof mod[exportName] !== 'function'. So the export exists (you got past 130) but is not callable. Like 130 it is rewrapped into `{kind: 2, message}` after stripping Parcel frames out of the stack so the Rust layer can surface a clean macro-execution error.

Source

Thrown at packages/transformers/js/src/JSTransformer.js:578

                    asset.invalidateOnFileChange(filePath);
                  },
                  invalidateOnFileCreate(invalidation) {
                    asset.invalidateOnFileCreate(invalidation);
                  },
                  invalidateOnEnvChange(env) {
                    asset.invalidateOnEnvChange(env);
                  },
                  invalidateOnStartup() {
                    asset.invalidateOnStartup();
                  },
                  invalidateOnBuild() {
                    asset.invalidateOnBuild();
                  },
                };

                return mod[exportName].apply(ctx, args);
              } else {
                throw new Error(
                  `"${exportName}" in "${src}" is not a function.`,
                );
              }
            } catch (err) {
              // Remove parcel core from stack and build string so Rust can process errors more easily.
              let stack = (err.stack || '').split('\n').slice(1);
              let message = err.message;
              for (let line of stack) {
                if (line.includes(__filename)) {
                  break;
                }
                message += '\n' + line;
              }
              throw {
                kind: 2,
                message,
              };
            }

View on GitHub (pinned to 59484858a1)

Solutions

  1. Inspect the export in the macro module: `console.log(typeof require('pkg').foo)` — it must be 'function'.
  2. Pick the correct function export name from the package.
  3. Pin/upgrade the macro package to a version that ships a function for that export.
  4. If you own the macro, export a function (or a curried factory) rather than a plain object.

Example fix

// before: config exported as an object
export const theme = { color: 'red' };
// macro call: theme({primary: 'color'}) -> not a function

// after
export function theme(opts) { return `...`; }
Defensive patterns

Strategy: type-guard

Validate before calling

function assertMacroCallable(mod, exportName) {
  if (typeof mod[exportName] !== 'function') {
    throw new TypeError(`${exportName} in macro module is ${typeof mod[exportName]}, expected function`);
  }
}

Type guard

function isMacroFunction(mod, exportName) {
  return typeof mod?.[exportName] === 'function';
}

Prevention

When it happens

Trigger: A macro call site names a valid export that is a value/object/constant rather than a function. The macro machinery only supports function exports because it invokes them with a MacroContext and the call's argument list.

Common situations: Package rename that turned a function export into a constant; importing a non-function sibling export by mistake; version skew where the macro was replaced by a config object; calling a macro before its declaration in the same module so the binding is still a let-placeholder.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/43ce304e51449547. Report an issue: GitHub.