parcel-bundler/parcel · error · ThrowableDiagnostic

Declared output format "${descriptor.outputFormat}" does not

Error message

Declared output format "${descriptor.outputFormat}" does not match expected output format "${inferredOutputFormat}".

What it means

Parcel infers the correct outputFormat from the distEntry extension and package.json `type` field. If you explicitly set `descriptor.outputFormat` and it disagrees with the inferred format, the build aborts. The expected extensions per format are listed (.mjs/.js for esmodule, .cjs/.js for commonjs, .js for global).

Source

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

        typeof pkgContents === 'string'
          ? pkgContents
          : // $FlowFixMe
            JSON.stringify(pkgContents, null, '\t');
      let expectedExtensions;
      switch (descriptor.outputFormat) {
        case 'esmodule':
          expectedExtensions = ['.mjs', '.js'];
          break;
        case 'commonjs':
          expectedExtensions = ['.cjs', '.js'];
          break;
        case 'global':
          expectedExtensions = ['.js'];
          break;
      }
      // $FlowFixMe
      let listFormat = new Intl.ListFormat('en-US', {type: 'disjunction'});
      throw new ThrowableDiagnostic({
        diagnostic: {
          message: md`Declared output format "${descriptor.outputFormat}" does not match expected output format "${inferredOutputFormat}".`,
          origin: '@parcel/core',
          codeFrames: [
            {
              language: 'json',
              filePath: pkgFilePath ?? undefined,
              code: contents,
              codeHighlights: generateJSONCodeHighlights(contents, [
                {
                  key: `/targets/${targetName}/outputFormat`,
                  type: 'value',
                  message: 'Declared output format defined here',
                },
                {
                  key: nullthrows(inferredOutputFormatField),
                  type: 'value',
                  message: 'Inferred output format defined here',

View on GitHub (pinned to 59484858a1)

Solutions

  1. Align the explicit outputFormat with the extension (e.g. esmodule + .mjs, commonjs + .cjs).
  2. Remove the explicit outputFormat and let Parcel infer it from the extension/type.
  3. Adjust the extension or `"type"` field to match the desired format.

Example fix

// before (package.json)
{
  "main": "dist/index.cjs",
  "targets": { "main": { "outputFormat": "esmodule" } }
}

// after
{
  "main": "dist/index.mjs",
  "targets": { "main": { "outputFormat": "esmodule" } }
}
Defensive patterns

Strategy: validation

Validate before calling

function inferFormat(entry, pkgType) {
  if (entry.endsWith('.mjs')) return 'esmodule';
  if (entry.endsWith('.cjs')) return 'commonjs';
  return pkgType === 'module' ? 'esmodule' : 'commonjs';
}
function assertFormatMatches(targets, pkg) {
  for (const [name, d] of Object.entries(targets || {})) {
    if (!d.outputFormat) continue;
    const inferred = inferFormat(d.distEntry || pkg[name], pkg.type);
    if (d.outputFormat !== inferred) {
      throw new Error(`Target ${name}: outputFormat ${d.outputFormat} != inferred ${inferred}`);
    }
  }
}

Type guard

function outputFormatCoherent(d, inferred) {
  return d.outputFormat == null || d.outputFormat === inferred;
}

Try / catch

try { await parcel.run(); } catch (e) {
  if (/does not match expected output format/.test(e.message)) {
    console.error('Align explicit outputFormat with extension/package type.');
  } else throw e;
}

Prevention

When it happens

Trigger: Setting `targets.<name>.outputFormat` to a value that conflicts with the extension/type-derived format for that target's distEntry.

Common situations: Hardcoding outputFormat while changing extensions; package.json `"type": "module"` interacting with a `commonjs` outputFormat setting; partial config migrations where format and extension drift apart.

Related errors


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