parcel-bundler/parcel · error · ThrowableDiagnostic

Unexpected output file type ${ext} in target "${targetName}"

Error message

Unexpected output file type ${ext} in target "${targetName}"

What it means

For a common named target (main/module/browser/types, defined in COMMON_TARGETS), Parcel validates that the configured `distEntry` (the output file path) has one of the expected extensions for that target type. If the extension is not in the allowed set, the build aborts with a disjunction list of allowed extensions.

Source

Thrown at packages/core/core/src/requests/TargetRequest.js:741

          continue;
        }

        if (
          distEntry != null &&
          !COMMON_TARGETS[targetName].match.test(distEntry)
        ) {
          let contents: string =
            typeof pkgContents === 'string'
              ? pkgContents
              : // $FlowFixMe
                JSON.stringify(pkgContents, null, '\t');
          // $FlowFixMe
          let listFormat = new Intl.ListFormat('en-US', {type: 'disjunction'});
          let extensions = listFormat.format(
            COMMON_TARGETS[targetName].extensions,
          );
          let ext = path.extname(distEntry);
          throw new ThrowableDiagnostic({
            diagnostic: {
              message: md`Unexpected output file type ${ext} in target "${targetName}"`,
              origin: '@parcel/core',
              codeFrames: [
                {
                  language: 'json',
                  filePath: pkgFilePath ?? undefined,
                  code: contents,
                  codeHighlights: generateJSONCodeHighlights(contents, [
                    {
                      key: pointer,
                      type: 'value',
                      message: `File extension must be ${extensions}`,
                    },
                  ]),
                },
              ],
              hints: [

View on GitHub (pinned to 59484858a1)

Solutions

  1. Align the distEntry file extension with the target's expected extensions shown in the error (use one of the listed extensions).
  2. If you intentionally want a different format, configure `targets.<name>.outputFormat` and the matching extension explicitly.
  3. Remove the distEntry override and let Parcel infer the correct extension.

Example fix

// before (package.json)
{
  "module": "dist/index.cjs"
}

// after
{
  "module": "dist/index.mjs"
}
Defensive patterns

Strategy: validation

Validate before calling

const COMMON_TARGETS = {
  main: ['js','cjs'], module: ['mjs','js'], browser: ['js'], types: ['d.ts']
};
function assertDistEntryExt(targetName, distEntry) {
  const ext = distEntry.split('.').pop();
  const allowed = COMMON_TARGETS[targetName];
  if (allowed && !allowed.includes(ext)) {
    throw new Error(`Target ${targetName} expects .${allowed.join('|')}, got .${ext}`);
  }
}

Type guard

function isValidDistEntryForTarget(targetName, distEntry, allowed) {
  const ext = distEntry.slice(distEntry.lastIndexOf('.') + 1);
  return allowed.includes(ext);
}

Try / catch

try { await parcel.run(); } catch (e) {
  if (/Unexpected output file type/.test(e.message)) {
    console.error('Fix the distEntry extension to match the target format.');
  } else throw e;
}

Prevention

When it happens

Trigger: Setting a distEntry for a COMMON_TARGET whose file extension differs from the target's expected set (e.g. pointing `module` at a `.cjs` file, or `main` at a `.mjs` while expecting commonjs).

Common situations: Mismatched field/extension pairs in package.json (e.g. `"main": "dist/index.mjs"` without esmodule config); leftover output paths after switching build format; copy-paste of build config between projects using different module formats.

Related errors


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