evanw/esbuild · error · Error

Must specify "kind" when calling "resolve"

Error message

Must specify "kind" when calling "resolve"

What it means

The plugin `resolve()` helper (lib/shared/common.ts:1268) requires a `kind` option that tells esbuild what kind of import is being resolved (e.g. `'import-statement'`, `'entry-point'`, `'require-call'`). The code reads `kind` with `mustBeString` and, if it is null/undefined, throws this error before sending the resolve request to the service.

Solutions

  1. Always pass a `kind` string matching one of the documented ResolveKind values (e.g. `'import-statement'`, `'entry-point'`, `'require-call'`, `'dynamic-import'`).
  2. Inside an onResolve hook, propagate the incoming `args.kind` so the value matches the real import context.

Example fix

// before
const r = await build.resolve('./foo');
// after
const r = await build.resolve('./foo', { kind: 'import-statement' });
Defensive patterns

Strategy: validation

Validate before calling

const RESOLVE_KINDS = ['entry-point','import-statement','require-call','dynamic-import','require-resolve','import-rule','url-token'];
function assertKind(kind: any) {
  if (typeof kind !== 'string' || !RESOLVE_KINDS.includes(kind)) throw new Error('Invalid/missing resolve kind');
}

Type guard

function isValidResolveKind(k: any): k is string {
  return typeof k === 'string' && ['entry-point','import-statement','require-call','dynamic-import','require-resolve','import-rule','url-token'].includes(k);
}

Prevention

When it happens

Trigger: Calling `build.resolve(path)` or `build.resolve(path, {})` without a `kind` field inside a plugin callback.

Common situations: Assuming `kind` has a default; porting code from a different resolver API; passing `kind` as part of a nested object instead of the options top level.

Related errors


AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09). Data as JSON: /api/errors/4357dea1952cb2c0. Report an issue: GitHub.

Appendix: source

Thrown at lib/shared/common.ts:1268

        let resolveDir = getFlag(options, keys, 'resolveDir', mustBeString)
        let kind = getFlag(options, keys, 'kind', mustBeString)
        let pluginData = getFlag(options, keys, 'pluginData', canBeAnything)
        let importAttributes = getFlag(options, keys, 'with', mustBeObject)
        checkForInvalidFlags(options, keys, 'in resolve() call')

        return new Promise((resolve, reject) => {
          const request: protocol.ResolveRequest = {
            command: 'resolve',
            path,
            key: buildKey,
            pluginName: name,
          }
          if (pluginName != null) request.pluginName = pluginName
          if (importer != null) request.importer = importer
          if (namespace != null) request.namespace = namespace
          if (resolveDir != null) request.resolveDir = resolveDir
          if (kind != null) request.kind = kind
          else throw new Error(`Must specify "kind" when calling "resolve"`)
          if (pluginData != null) request.pluginData = details.store(pluginData)
          if (importAttributes != null) request.with = sanitizeStringMap(importAttributes, 'with')

          sendRequest<protocol.ResolveRequest, protocol.ResolveResponse>(refs, request, (error, response) => {
            if (error !== null) reject(new Error(error))
            else resolve({
              errors: replaceDetailsInMessages(response!.errors, details),
              warnings: replaceDetailsInMessages(response!.warnings, details),
              path: response!.path,
              external: response!.external,
              sideEffects: response!.sideEffects,
              namespace: response!.namespace,
              suffix: response!.suffix,
              pluginData: details.load(response!.pluginData),
            })
          })
        })
      }

View on GitHub (pinned to f6058f8364)