Skip to content

Multi-chunk file uploads fail: nonce refreshed mid-upload rejects every chunk after the first (regression) #660

Description

@milicavs

Summary

Any file large enough to split into multiple 2 MB chunks fails to upload. An orphaned .part of exactly 2,097,152 bytes is left in wp-content/uploads/ppom_files/, and the user sees "You cannot upload the file at this time, please refresh the page and try again." Files under the chunk size (single-chunk) upload fine.

Regression

Introduced by #575 (79761f1, 2026-05-07), "fix: intermittent file upload failures for users" — the nonce-refresh feature. Before it, all chunks of a file used the same page nonce; the mechanism below did not exist.

Root cause

The uploader's BeforeUpload handler (js/file-upload.js) is async and awaits ppom_refresh_file_nonces(), but plupload does not await async handlers:

  1. Chunk 0 is sent immediately with the original page nonce → passes Handler::upload_file() nonce check (~line 219) → writes the first 2 MB.
  2. The refresh then resolves and swaps multipart_params.ppom_nonce to a new nonce via setOption.
  3. Chunks 1..N send the new nonce → rejected at the same nonce check → error → reassembly never continues.

Evidence (reproduced)

  • 3 chunked ppom_upload_file POSTs, all HTTP 200. Chunk 0 → [] (success); chunks 1 & 2 → {"status":"error","message":"You cannot upload the file..."}.
  • .part frozen at exactly 2,097,152 bytes.

Not a reassembly bug

Handler::create_chunk_file() append/finalize logic is correct (appends with ab, finalizes on the last chunk). The failure is nonce rejection before the append, not bad stitching.

Fix direction (not yet decided)

Ensure every chunk of a file uses one consistent, valid nonce — e.g. refresh once when the file is added and apply it before the first chunk, or skip refresh for an in-progress chunked upload — without reintroducing the stale-nonce problem #575 addressed.

Related

Metadata

Metadata

Labels

bugThis label could be used to identify issues that are caused by a defect in the product.customer reportIndicates the request came from a customer.regressionIssue represents a change in behavior from a previous version that is not intended or desired..

Type

Fields

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions