{"record":{"id":"d9c3d274a01858bc","repo":"evanw/esbuild","slug":"expected-onload-callback-in-plugin-quote-name","errorCode":null,"errorMessage":"Expected onLoad() callback in plugin ${quote(name)} to return an object","messagePattern":"Expected onLoad\\(\\) callback in plugin (.+?) to return an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/shared/common.ts","lineNumber":1450,"sourceCode":"    }\n    sendResponse(id, response as any)\n  }\n\n  requestCallbacks['on-load'] = async (id, request: protocol.OnLoadRequest) => {\n    let response: protocol.OnLoadResponse = {}, name = '', callback, note\n    for (let id of request.ids) {\n      try {\n        ({ name, callback, note } = onLoadCallbacks[id])\n        let result = await callback({\n          path: request.path,\n          namespace: request.namespace,\n          suffix: request.suffix,\n          pluginData: details.load(request.pluginData),\n          with: request.with,\n        })\n\n        if (result != null) {\n          if (typeof result !== 'object') throw new Error(`Expected onLoad() callback in plugin ${quote(name)} to return an object`)\n          let keys: OptionKeys = {}\n          let pluginName = getFlag(result, keys, 'pluginName', mustBeString)\n          let contents = getFlag(result, keys, 'contents', mustBeStringOrUint8Array)\n          let resolveDir = getFlag(result, keys, 'resolveDir', mustBeString)\n          let pluginData = getFlag(result, keys, 'pluginData', canBeAnything)\n          let loader = getFlag(result, keys, 'loader', mustBeString)\n          let errors = getFlag(result, keys, 'errors', mustBeArray)\n          let warnings = getFlag(result, keys, 'warnings', mustBeArray)\n          let watchFiles = getFlag(result, keys, 'watchFiles', mustBeArrayOfStrings)\n          let watchDirs = getFlag(result, keys, 'watchDirs', mustBeArrayOfStrings)\n          checkForInvalidFlags(result, keys, `from onLoad() callback in plugin ${quote(name)}`)\n\n          response.id = id\n          if (pluginName != null) response.pluginName = pluginName\n          if (contents instanceof Uint8Array) response.contents = contents\n          else if (contents != null) response.contents = protocol.encodeUTF8(contents)\n          if (resolveDir != null) response.resolveDir = resolveDir\n          if (pluginData != null) response.pluginData = details.store(pluginData)","sourceCodeStart":1432,"sourceCodeEnd":1468,"githubUrl":"https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/lib/shared/common.ts#L1432-L1468","documentation":"When an `onLoad` callback runs (lib/shared/common.ts:1450), its awaited return value must be `null`/`undefined` or an object with fields like `contents`, `loader`, `resolveDir`, `errors`, `warnings`. A truthy non-object (e.g. a string of source code, a Uint8Array, a number) triggers this error.","triggerScenarios":"An onLoad callback that returns a string of file contents directly instead of `{ contents: ... }`.","commonSituations":"Returning raw source text; returning the file contents Buffer; returning a boolean to indicate success.","solutions":["Return an object such as `{ contents: sourceText, loader: 'js', resolveDir: dir }`, or `null` to defer.","Wrap any raw contents (string or Uint8Array) inside the `contents` field."],"exampleFix":"// before\nbuild.onLoad({ filter: /.*/ }, args => fs.readFileSync(args.path, 'utf8'));\n// after\nbuild.onLoad({ filter: /.*/ }, args => ({ contents: fs.readFileSync(args.path, 'utf8'), loader: 'ts' }));","handlingStrategy":"type-guard","validationCode":"function wrapOnLoad(cb) {\n  return async (args) => { const r = await cb(args); if (r != null && typeof r !== 'object') throw new Error('onLoad must return object or null'); return r; };\n}","typeGuard":"function isOnLoadResult(v: any): v is { contents?: string | Uint8Array; loader?: string } | null {\n  return v == null || (typeof v === 'object' && !Array.isArray(v));\n}","tryCatchPattern":null,"preventionTips":["Wrap contents in { contents, loader }.","Return null to defer to the next plugin."],"tags":["plugins","onload","validation","callback-contract"],"backgroundTag":null,"analyzedSha":"f6058f8364fe7ab91ca57a83e02577ed74c9cae4","analyzedAt":"2026-08-09T18:37:22.223Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}