{"id":"e01b51ef6c56221e","repo":"sindresorhus/got","slug":"non-native-formdata-is-not-supported-use-globalth","errorCode":null,"errorMessage":"Non-native FormData is not supported. Use globalThis.FormData instead.","messagePattern":"Non-native FormData is not supported\\. Use globalThis\\.FormData instead\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"source/core/index.ts","lineNumber":946,"sourceCode":"\t\t\tconst noContentType = !is.string(headers['content-type']);\n\n\t\t\tif (isBody) {\n\t\t\t\t// Native FormData\n\t\t\t\tif (options.body instanceof FormData) {\n\t\t\t\t\tconst {body, contentType} = serializeNativeFormDataBody(options.body);\n\t\t\t\t\tthis._nativeFormDataBody = {\n\t\t\t\t\t\tform: options.body,\n\t\t\t\t\t\tbody,\n\t\t\t\t\t\tcontentTypeWasGenerated: noContentType,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (noContentType) {\n\t\t\t\t\t\theaders['content-type'] = contentType;\n\t\t\t\t\t}\n\n\t\t\t\t\toptions.body = body;\n\t\t\t\t} else if (Object.prototype.toString.call(options.body) === '[object FormData]') {\n\t\t\t\t\tthrow new TypeError('Non-native FormData is not supported. Use globalThis.FormData instead.');\n\t\t\t\t}\n\t\t\t} else if (isForm) {\n\t\t\t\tif (noContentType) {\n\t\t\t\t\theaders['content-type'] = 'application/x-www-form-urlencoded';\n\t\t\t\t}\n\n\t\t\t\tconst {form} = options;\n\t\t\t\toptions.form = undefined;\n\n\t\t\t\toptions.body = (new URLSearchParams(form)).toString();\n\t\t\t} else {\n\t\t\t\tif (noContentType) {\n\t\t\t\t\theaders['content-type'] = 'application/json';\n\t\t\t\t}\n\n\t\t\t\tconst {json} = options;\n\t\t\t\toptions.json = undefined;\n","sourceCodeStart":928,"sourceCodeEnd":964,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/index.ts#L928-L964","documentation":"Thrown at source/core/index.ts:946 during body finalization. got only accepts the native platform FormData (`globalThis.FormData`, available in Node 18+) for multipart bodies. The check uses `Object.prototype.toString.call(options.body) === '[object FormData]'` to detect objects that pretend to be FormData (report the same toString tag) but fail the `instanceof FormData` check above. This guards against form-data polyfills (e.g. the older `form-data` package) whose serialization contract differs from the native one and would produce malformed requests.","triggerScenarios":"Importing the `form-data` npm package and passing its instance as `body`; using a custom class whose `[Symbol.toStringTag]` is 'FormData'; passing a FormData-like object from an older shim that predates globalThis.FormData.","commonSituations":"Migrating from axios or request which historically used the `form-data` polyfill; copying snippets from older Node tutorials; running on a runtime that doesn't expose globalThis.FormData and shimming it with a non-compliant polyfill.","solutions":["Use the native `new FormData()` (globalThis.FormData) — drop the `form-data` package import.","If you have an old `form-data` instance, convert it to native FormData by appending each field, or send it as a stream with an explicit content-type header instead.","Upgrade to Node >= 18 (got v15 already requires Node >= 22 per package.json) where globalThis.FormData is built in."],"exampleFix":"// before\nimport FormData from 'form-data';\nconst form = new FormData();\nform.append('file', fs.createReadStream(path));\nawait got.post(url, { body: form });\n\n// after — native FormData\nconst form = new FormData(); // globalThis.FormData\nform.append('file', new Blob([fs.readFileSync(path)]), 'file.txt');\nawait got.post(url, { body: form });","handlingStrategy":"type-guard","validationCode":"// Reject polyfilled FormData before calling got.\nfunction assertNativeFormData(body) {\n  if (body && Object.prototype.toString.call(body) === '[object FormData]' && !(body instanceof globalThis.FormData)) {\n    throw new TypeError('Pass a native globalThis.FormData instance, not a polyfill.');\n  }\n}\nassertNativeFormData(options.body);\nawait got(url, options);","typeGuard":"function isNativeFormData(v: unknown): v is FormData {\n  return v instanceof globalThis.FormData;\n}\n\nfunction isFormDataImposter(v: unknown): boolean {\n  return v !== null && typeof v === 'object'\n    && Object.prototype.toString.call(v) === '[object FormData]'\n    && !(v instanceof globalThis.FormData);\n}","tryCatchPattern":"try {\n  await got.post(url, { body: form });\n} catch (error) {\n  if (error instanceof TypeError && /Non-native FormData is not supported/.test(error.message)) {\n    // convert polyfill to native FormData, then retry\n    throw new Error('Replace the form-data polyfill with globalThis.FormData', { cause: error });\n  }\n  throw error;\n}","preventionTips":["Use `new FormData()` (globalThis.FormData) — drop the `form-data` npm package import.","Require Node >= 18 (got v15 requires Node >= 22) where FormData is built in.","If you have a polyfill instance, convert its fields to native FormData before passing."],"tags":["formdata","multipart","polyfill","node-version"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}