Skip to content

Recreate a deleted temp directory instead of failing all later buffered requests #68622

Description

@VAllens

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When ASP.NET Core spills a large multipart request or a large buffered response to disk, it writes ASPNETCORE_*.tmp under ASPNETCORE_TEMP or Path.GetTempPath().

AspNetCoreTempDirectory caches that path for the process lifetime. If the directory is later missing (disk cleanup, an operator deleting the folder, Windows removing Temp\{sessionId}), the framework throws DirectoryNotFoundException instead of creating the directory it already resolved. Later requests that exceed the memory threshold keep failing until something outside the process recreates the folder.

For IFormFile binding this happens in FormFeature before user endpoint code runs, so the app cannot recover inside the action. Setting ASPNETCORE_TEMP to a “stable” folder does not help if that folder is deleted while the process is still running.

Related but not a duplicate of #42647 (locked). That issue was answered as: %TEMP% does not update after process start, so point ASPNETCORE_TEMP at a directory that already exists. This report is the other failure mode: the path is already known, but the directory was deleted.

Expected Behavior

Before creating ASPNETCORE_*.tmp, call Directory.CreateDirectory on the already resolved path (no-op if it exists). If create or the subsequent open fails (permissions, read-only volume), throw as today.

Do not change how the path is chosen (ASPNETCORE_TEMP then Path.GetTempPath()). Do not try to refresh %TEMP% or allocate a new Windows session-id folder.

Steps To Reproduce

  1. Host an API that accepts IFormFile (multipart upload larger than FormOptions.MemoryBufferThreshold / the rewind threshold).
  2. Optionally set ASPNETCORE_TEMP to a dedicated folder (the workaround from aspnetcore Abnormal prompt during operation  #42647), or use the default Path.GetTempPath().
  3. Ensure the folder exists, start the app, and confirm the upload succeeds.
  4. Delete that folder. Do not restart the process.
  5. Repeat the same upload.

Exceptions (if any)

2026-08-18 17:26:12.676 [DBG] Reading the request body failed with an IOException. |7|System.IO.DirectoryNotFoundException: C:\Users\Administrator\AppData\Local\Temp\2\
   at Obfuscation.Web!<BaseAddress>+0x391f5
   at Obfuscation.Web!<BaseAddress>+0x1090d1
   at Obfuscation.Web!<BaseAddress>+0x10eeb0
--- End of stack trace from previous location ---
   at Obfuscation.Web!<BaseAddress>+0x3767b0
   at Obfuscation.Web!<BaseAddress>+0x378d07
   at Obfuscation.Web!<BaseAddress>+0x378c2b
   at Obfuscation.Web!<BaseAddress>+0x111b70
--- End of stack trace from previous location ---
   at Obfuscation.Web!<BaseAddress>+0x3767b0
   at Obfuscation.Web!<BaseAddress>+0x378d07
   at Obfuscation.Web!<BaseAddress>+0x378c2b
   at Obfuscation.Web!<BaseAddress>+0x4377e
--- End of stack trace from previous location ---
   at Obfuscation.Web!<BaseAddress>+0x3767b0
   at Obfuscation.Web!<BaseAddress>+0x378d07
   at Obfuscation.Web!<BaseAddress>+0x378c2b
   at Obfuscation.Web!<BaseAddress>+0x1d1e12

Often wrapped as:

Reading the request body failed with an IOException.

Typical stacks:

  • Request: FormFeature.InnerReadFormAsync → FileBufferingReadStream.CreateTempFile → AspNetCoreTempDirectory.TempDirectory or new FileStream(...)
  • Response: FileBufferingWriteStream.EnsureFileStream (same as aspnetcore Abnormal prompt during operation  #42647)

.NET Version

10.0.400

Anything else?

  • ASP.NET Core version: current main (also observed on shipped versions that use AspNetCoreTempDirectory).
  • OS: Windows (also applies anywhere the resolved temp directory can be deleted while the process is running).

Call path for IFormFile:

  1. FormFeature.InnerReadFormAsync (src/Http/Http/src/Features/FormFeature.cs)
  2. section.EnableRewind(...) → FileBufferingReadStream (src/Http/Http/src/Internal/BufferingHelper.cs)
  3. Over threshold → FileBufferingReadStream.CreateTempFile() (src/Http/WebUtilities/src/FileBufferingReadStream.cs)
  4. AspNetCoreTempDirectory currently throws if the directory is missing, and caches the path after the first successful lookup

I have a small patch ready (create the resolved directory in AspNetCoreTempDirectory and again immediately before creating the temp file in FileBufferingReadStream / FileBufferingWriteStream) and can open a PR against main if this approach is acceptable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions