pnpm/pnpm · error · PnpmError

ERR_PNPM_UNSUPPORTED_RESOLUTION_TYPE

ERR_PNPM_UNSUPPORTED_RESOLUTION_TYPE

Error message

Cannot fetch dependency with custom resolution type "${resolution.type}". Custom resolutions must be handled by custom fetchers.

What it means

pick-fetcher classifies each resolution and dispatches to a built-in fetcher (registry tarball, git, local dir, binary, ...). When classifyResolution returns 'custom', no built-in exists by construction — custom resolution types are only fetchable through custom fetchers registered programmatically by an embedding application. Hitting this from a stock install means a custom resolution leaked into the graph without its fetcher.

Source

Thrown at pnpm11/fetching/pick-fetcher/src/index.ts:72

            },
            { resolutionNeedsFetch }
          ) as FetchFunction
        }
      }
    }
  }

  return pickBuiltinFetcher(fetcherByHostingType, resolution)
}

function isCustomFetcherDelegation (result: FetchResult | CustomFetcherDelegation): result is CustomFetcherDelegation {
  return result != null && typeof result === 'object' && 'delegate' in result && !('filesMap' in result)
}

function pickBuiltinFetcher (fetcherByHostingType: Fetchers, resolution: AtomicResolution): PickedFetcher {
  const fetcherType = classifyResolution(resolution)
  if (fetcherType === 'custom') {
    throw new PnpmError(
      'UNSUPPORTED_RESOLUTION_TYPE',
      `Cannot fetch dependency with custom resolution type "${resolution.type}". ` +
      'Custom resolutions must be handled by custom fetchers.'
    )
  }

  const fetch = fetcherByHostingType[fetcherType]

  if (!fetch) {
    throw new Error(`Fetching for dependency type "${resolution.type ?? 'tarball'}" is not supported`)
  }

  return fetch
}

View on GitHub (pinned to 6261b7f388)

Solutions

  1. Remove the custom resolution from package.json and the lockfile, or replace it with a supported protocol (npm, git, tarball URL, file:, link:)
  2. If you depend on custom resolutions, run installs through the tool that registers the matching custom fetcher
  3. Regenerate the lockfile in the environment that owns those resolutions

Example fix

// before
{ "dependencies": { "mydb": "myproto://host/thing" } }

// after
{ "dependencies": { "mydb": "github:owner/mydb-adapter" } }
Defensive patterns

Strategy: type-guard

Type guard

type BuiltinResolutionType = 'registry' | 'git' | 'tarball' | 'directory' | 'binary'

const CUSTOM_TYPES = new Set(['custom']) // whatever your pipeline defines

function needsCustomFetcher (resolution: { type?: string }): boolean {
  return resolution.type != null && CUSTOM_TYPES.has(resolution.type)
}

// before building the fetcher pipeline
if (graphResolutions.some(needsCustomFetcher) && customFetchers.length === 0) {
  throw new Error('lockfile contains custom resolutions but no custom fetcher is registered')
}

Try / catch

try {
  await pickFetcherAndFetch(resolution)
} catch (err) {
  if (err instanceof PnpmError && err.code === 'ERR_PNPM_UNSUPPORTED_RESOLUTION_TYPE') {
    // No retry will help: register the fetcher or strip the resolution
    throw new Error(`no fetcher for custom type '${resolution.type}'; register one or use a builtin protocol`, { cause: err })
  }
  throw err
}

Prevention

When it happens

Trigger: A lockfile/resolution record with a custom type field reaches pickBuiltinFetcher (and its caller did not supply a matching custom fetcher, or earlier custom-fetcher delegation did not match). Typical with plugins or programmatic pipelines that drop their fetcher registration.

Common situations: Lockfiles authored for a plugin-based pnpm wrapper run under plain pnpm; programmatic consumers that build the fetchers map but forget to include their custom fetcher; version skew after a wrapper upgrade.

Related errors


AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17). Data as JSON: /api/errors/9630f298de957424. Report an issue: GitHub.