{"record":{"id":"bc3725f461bda88f","repo":"dotnet/aspnetcore","slug":"unable-to-read-the-antiforgery-request-token-from","errorCode":null,"errorMessage":"Unable to read the antiforgery request token from the posted form.","messagePattern":"Unable to read the antiforgery request token from the posted form\\.","errorType":"exception","errorClass":"AntiforgeryValidationException","httpStatus":null,"severity":"error","filePath":"src/Antiforgery/src/Internal/DefaultAntiforgeryTokenStore.cs","lineNumber":64,"sourceCode":"        {\n            requestToken = httpContext.Request.Headers[_options.HeaderName];\n        }\n\n        // Fall back to reading form instead\n        if (requestToken.Count == 0 && httpContext.Request.HasFormContentType && !_options.SuppressReadingTokenFromFormBody)\n        {\n            // Check the content-type before accessing the form collection to make sure\n            // we report errors gracefully.\n            IFormCollection form;\n            try\n            {\n                form = await httpContext.Request.ReadFormAsync();\n            }\n            catch (InvalidDataException ex)\n            {\n                // ReadFormAsync can throw InvalidDataException if the form content is malformed.\n                // Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.\n                throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);\n            }\n            catch (IOException ex)\n            {\n                // Reading the request body (which happens as part of ReadFromAsync) may throw an exception if a client disconnects.\n                // Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.\n                throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);\n            }\n\n            requestToken = form[_options.FormFieldName];\n        }\n\n        return new AntiforgeryTokenSet(requestToken, cookieToken, _options.FormFieldName, _options.HeaderName);\n    }\n\n    public void SaveCookieToken(HttpContext httpContext, string token)\n    {\n        Debug.Assert(httpContext != null);\n        Debug.Assert(token != null);","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Antiforgery/src/Internal/DefaultAntiforgeryTokenStore.cs#L46-L82","documentation":"Thrown by DefaultAntiforgeryTokenStore when ReadFormAsync raises InvalidDataException while reading the posted form. The store wraps it in AntiforgeryValidationException so the pipeline treats it as a normal antiforgery failure (typically a 400) rather than a server error. Malformed form content is the root cause.","triggerScenarios":"A request whose multipart/form-data or URL-encoded body is malformed (bad boundary, oversized fields beyond limits, corrupt multipart, invalid characters) reaches GetRequestTokensAsync, and ReadFormAsync throws InvalidDataException.","commonSituations":"Client constructing multipart bodies by hand with an incorrect boundary; upload exceeding Kestrel/IIS form size limits; a truncated body from a network drop or a misbehaving proxy; encoded content that violates the form parser rules.","solutions":["Inspect the raw request (boundary, Content-Type, body) and fix the malformed multipart construction on the client.","Raise FormOptions.MultipartBodyLengthLimit / Kestrel limits if the upload legitimately exceeds defaults and the error is masking a size rejection.","Ensure any proxy between client and server forwards the full body and Content-Type unchanged.","Reproduce with a known-good form (e.g. a real <form> submit) to confirm the client code is the source of the malformed body."],"exampleFix":"// before: hand-built multipart with wrong boundary\nconst body = '--boundary\\r\\nfield=value';\n\n// after: use FormData, which builds a valid multipart body\nconst fd = new FormData();\nfd.append('field', 'value');\nawait fetch('/submit', { method:'POST', body: fd });","handlingStrategy":"try-catch","validationCode":"// Validate request body basics before reading form: ensure Content-Type is multipart/form-data and body length <= configured limit.","typeGuard":null,"tryCatchPattern":"try { await httpContext.Request.ReadFormAsync(); }\ncatch (InvalidDataException ex) { /* treat as 400, log detail */ }","preventionTips":["Use framework form builders (FormData, <form>) rather than hand-rolled multipart.","Raise form size limits only when justified and document the new limits.","Add an integration test posting a malformed multipart body to assert a 400."],"tags":["antiforgery","aspnetcore","form","validation","request-parsing"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}