parcel-bundler/parcel · error · ThrowableDiagnostic

Local plugins are not supported in Parcel config packages. P

Error message

Local plugins are not supported in Parcel config packages. Please publish "${pluginName}" as a separate npm package.

What it means

A Parcel *config package* (a published `.parcelrc`-bearing npm package) may reference plugins, but every plugin it references must itself be a separately-published npm package. This is enforced so plugins remain individually mixable across configs. Referencing a plugin by a relative path (starting with `.`) inside the config package is rejected with this diagnostic, including a code frame of the offending `.parcelrc`.

Source

Thrown at packages/core/core/src/loadParcelPlugin.js:47

): Promise<{|
  plugin: T,
  version: Semver,
  resolveFrom: ProjectPath,
  range: ?SemverRange,
|} | null> {
  let resolveFrom = configPath;
  let range;
  let isOptional = false;
  if (
    resolveFrom.includes(NODE_MODULES) ||
    (process.env.PARCEL_BUILD_ENV !== 'production' &&
      /packages[/\\]configs/.test(resolveFrom))
  ) {
    // Config packages can reference plugins, but cannot contain other plugins within them.
    // This forces every published plugin to be published separately so they can be mixed and matched if needed.
    if (pluginName.startsWith('.')) {
      let configContents = await options.inputFS.readFile(configPath, 'utf8');
      throw new ThrowableDiagnostic({
        diagnostic: {
          message: md`Local plugins are not supported in Parcel config packages. Please publish "${pluginName}" as a separate npm package.`,
          origin: '@parcel/core',
          codeFrames: keyPath
            ? [
                {
                  filePath: configPath,
                  language: 'json5',
                  code: configContents,
                  codeHighlights: generateJSONCodeHighlights(configContents, [
                    {
                      key: keyPath,
                      type: 'value',
                    },
                  ]),
                },
              ]
            : undefined,

View on GitHub (pinned to 59484858a1)

Solutions

  1. Publish the local plugin as its own npm package and reference it by name.
  2. If the plugin is project-specific, keep it in the consuming project's `.parcelrc` (local configs may use relative paths), not in a published config package.
  3. Move the relative plugin out of the config package into the app that uses it.

Example fix

// before (config package .parcelrc)
{ "transforms": { "*.css": ["./local-transformer.js"] } }

// after
{ "transforms": { "*.css": ["@your-scope/parcel-transformer-css"] } }
Defensive patterns

Strategy: validation

Validate before calling

// In a config package, reject relative plugin references at author time.
function isRelativePlugin(ref: string): boolean {
  return ref.startsWith('.');
}
if (isRelativePlugin(entry)) throw new Error('publish the plugin as a package');

Type guard

function isPublishedPluginName(ref: string): boolean {
  return !ref.startsWith('.');
}

Prevention

When it happens

Trigger: Inside a config package, a pipeline entry resolves to a relative file (e.g. `./my-plugin.js`) rather than an npm package name.

Common situations: Authoring a shared Parcel config and bundling helper plugins as local files inside it.

Related errors


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