{"record":{"id":"81805b60692e7e9b","repo":"payloadcms/payload","slug":"a-file-name-is-required","errorCode":null,"errorMessage":"A file name is required.","messagePattern":"A file name is required\\.","errorType":"exception","errorClass":"APIError","httpStatus":400,"severity":"error","filePath":"packages/payload/src/utilities/addDataAndFileToRequest.ts","lineNumber":67,"sourceCode":"      if (files) {\n        req.files = files\n        // Backwards compatibility: set req.file for standard upload collections\n        // Guard: if multiple files share the field name \"file\", files.file is an array — skip\n        if (files.file && !Array.isArray(files.file)) {\n          req.file = files.file\n        }\n      }\n\n      if (fields?._payload && typeof fields._payload === 'string') {\n        req.data = JSON.parse(fields._payload)\n      }\n\n      if (!req.file && fields?.file && typeof fields?.file === 'string') {\n        let uploadedFile: UploadInstructions['file']\n        try {\n          uploadedFile = JSON.parse(fields.file)\n        } catch {\n          throw new APIError('A file name is required.', 400)\n        }\n        const collectionSlug =\n          typeof req.routeParams?.collection === 'string'\n            ? req.routeParams.collection\n            : uploadedFile.collectionSlug\n        const uploadConfig = collectionSlug\n          ? req.payload.collections[collectionSlug]?.config.upload\n          : undefined\n\n        if (!collectionSlug || !uploadConfig) {\n          throw new APIError('Invalid upload collection.', 400)\n        }\n\n        req.file = await getFileFromUploadInstructions({\n          collectionSlug,\n          file: uploadedFile,\n          req,\n        })","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/utilities/addDataAndFileToRequest.ts#L49-L85","documentation":"Thrown when the multipart `file` field is a string that cannot be parsed as JSON. In the staged-upload flow, the `file` field on a multipart request is expected to contain a JSON-encoded `UploadInstructions['file']` object (including filename, collectionSlug, etc.), not a plain filename string.","triggerScenarios":"A multipart request includes `fields.file` as a plain string (e.g. `\"photo.jpg\"`) instead of a JSON object, or the JSON string is malformed. The `JSON.parse(fields.file)` call inside `addDataAndFileToRequest` then throws.","commonSituations":"Client is using the old upload convention (plain filename string) with a Payload version that expects the new staged-upload `UploadInstructions` JSON shape; the `file` field was double-stringified or corrupted by FormData serialization; a custom client constructs the multipart payload manually and puts the wrong value in `file`.","solutions":["Send the `file` field as a JSON-encoded `UploadInstructions['file']` object, not a plain filename.","If using the Payload REST API for uploads, use the SDK or follow the current docs for the exact multipart field shape.","Ensure FormData appends the JSON string correctly: `formData.append('file', JSON.stringify(instructionObject))`.","Upgrade the client to match the Payload version expected upload contract."],"exampleFix":"// before\nconst fd = new FormData()\nfd.append('file', 'photo.jpg') // plain string -> parse fails\n\n// after\nconst fd = new FormData()\nfd.append('file', JSON.stringify({\n  filename: 'photo.jpg',\n  mimeType: 'image/jpeg',\n  filesize: buf.byteLength,\n  collectionSlug: 'media',\n}))","handlingStrategy":"type-guard","validationCode":"// Ensure the file field is a valid JSON-encoded UploadInstructions object\nconst fileInstruction = JSON.stringify({\n  filename: file.name,\n  mimeType: file.type,\n  filesize: file.size,\n  collectionSlug: 'media',\n})\nJSON.parse(fileInstruction) // round-trip validation\nconst fd = new FormData()\nfd.append('file', fileInstruction) // JSON string, not plain filename","typeGuard":"const isUploadInstructionFile = (v) =>\n  !!v && typeof v === 'object'\n    && typeof v.filename === 'string'\n    && typeof v.mimeType === 'string'\n    && typeof v.filesize === 'number'\n    && typeof v.collectionSlug === 'string'","tryCatchPattern":"try {\n  await fetch(url, { method: 'POST', body: formData })\n} catch (e) {\n  if (e instanceof APIError && e.message === 'A file name is required.') {\n    // fix: send JSON-encoded file instruction instead of plain string\n  } else throw e\n}","preventionTips":["Use JSON.stringify on the UploadInstructions object for the multipart 'file' field.","Never pass a plain filename string as the file field in the staged-upload flow.","Round-trip test (parse what you stringify) before appending to FormData."],"tags":["upload","multipart","json","api-contract"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}