{"id":"58408af54fc05cc4","repo":"evanw/esbuild","slug":"plugin-at-index-i-is-missing-a-name","errorCode":null,"errorMessage":"Plugin at index ${i} is missing a name","messagePattern":"Plugin at index (.+?) is missing a name","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/shared/common.ts","lineNumber":1224,"sourceCode":"      callback: (args: types.OnLoadArgs) =>\n        (types.OnLoadResult | null | undefined | Promise<types.OnLoadResult | null | undefined>),\n    },\n  } = {}\n\n  let onDisposeCallbacks: (() => void)[] = []\n  let nextCallbackID = 0\n  let i = 0\n  let requestPlugins: protocol.BuildPlugin[] = []\n  let isSetupDone = false\n\n  // Clone the plugin array to guard against mutation during iteration\n  plugins = [...plugins]\n\n  for (let item of plugins) {\n    let keys: OptionKeys = {}\n    if (typeof item !== 'object') throw new Error(`Plugin at index ${i} must be an object`)\n    const name = getFlag(item, keys, 'name', mustBeString)\n    if (typeof name !== 'string' || name === '') throw new Error(`Plugin at index ${i} is missing a name`)\n    try {\n      let setup = getFlag(item, keys, 'setup', mustBeFunction)\n      if (typeof setup !== 'function') throw new Error(`Plugin is missing a setup function`)\n      checkForInvalidFlags(item, keys, `on plugin ${quote(name)}`)\n\n      let plugin: protocol.BuildPlugin = {\n        name,\n        onStart: false,\n        onEnd: false,\n        onResolve: [],\n        onLoad: [],\n      }\n      i++\n\n      let resolve = (path: string, options: types.ResolveOptions = {}): Promise<types.ResolveResult> => {\n        if (!isSetupDone) throw new Error('Cannot call \"resolve\" before plugin setup has completed')\n        if (typeof path !== 'string') throw new Error(`The path to resolve must be a string`)\n        let keys: OptionKeys = Object.create(null)","sourceCodeStart":1206,"sourceCodeEnd":1242,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/lib/shared/common.ts#L1206-L1242","documentation":"Every esbuild plugin must declare a non-empty name string so esbuild can attribute errors/warnings and route onResolve/onLoad callbacks. The check at lib/shared/common.ts:1224 fires when getFlag(name, mustBeString) yields undefined or the name is the empty string — both make the plugin unidentifiable. The name appears in error messages and in the resolve() pluginName option.","triggerScenarios":"Plugin object missing the 'name' key entirely. name: '' or name: undefined. name: 123 (mustBeString returns null so getFlag yields undefined).","commonSituations":"Authoring a plugin from a factory that takes { setup } and forgets to assign a name. Copy-pasting a plugin template and deleting name. Dynamic plugins built via Object.assign that overwrite name with undefined.","solutions":["Add name: 'my-plugin' (non-empty string) to every plugin object.","In a plugin factory, default the name: function makePlugin(opts){ return { name: opts.name || 'my-plugin', setup } }.","Add a unit test asserting all exported plugins have a non-empty string name."],"exampleFix":"// before\nexport default {\n  setup(build) { /* ... */ },\n};\n// after\nexport default {\n  name: 'my-plugin',\n  setup(build) { /* ... */ },\n};","handlingStrategy":"type-guard","validationCode":"function withName(p) {\n  if (typeof p.name !== 'string' || p.name === '') {\n    throw new Error(`Plugin must have a non-empty string name; got ${JSON.stringify(p.name)}`);\n  }\n  return p;\n}","typeGuard":"function hasPluginName(p): p is { name: string } {\n  return typeof p?.name === 'string' && p.name.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always include a name field when authoring plugins; use a factory that defaults it.","Add a unit test that asserts every exported plugin has a non-empty name.","Lint shared plugin code with a custom rule requiring name."],"tags":["plugins","validation","api-misuse"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}