Skip to content

Allow quota write streams with unknown free space - #61706

Open
veryCrunchy wants to merge 1 commit into
nextcloud:masterfrom
veryCrunchy:fix/quota-writestream-unknown-free-space
Open

Allow quota write streams with unknown free space#61706
veryCrunchy wants to merge 1 commit into
nextcloud:masterfrom
veryCrunchy:fix/quota-writestream-unknown-free-space

Conversation

@veryCrunchy

@veryCrunchyveryCrunchy commented Jul 1, 2026

Copy link
Copy Markdown

Summary

This PR allows quota-wrapped writeStream() calls to proceed when the reported free space is unknown.

With S3 primary object storage and a finite user quota, chunked WebDAV uploads can fail while writing chunks to the DAV upload staging path under uploads/.... For upload staging paths, Quota::free_space() delegates to the wrapped storage. Object-store-backed storage can report free space as unknown, but Quota::writeStream() currently compares the known stream size directly against that value and can raise NotEnoughSpaceException even though the user's destination quota has enough available space.

This changes Quota::writeStream() to treat unknown free space consistently with other quota wrapper write paths such as file_put_contents(), copy(), copyFromStorage(), and moveFromStorage().

A regression test covers writing a known-size stream to an uploads/... path when the wrapped storage reports unknown free space.

AI assistance was used to help inspect logs, reason through the relevant code path, draft the regression test, and organize validation. I prepared this patch after reproducing the issue on an affected Nextcloud instance. After the fix was drafted and tested locally, I found the existing report in #61488 and linked this PR to that issue.

Validation performed:

./autotest.sh sqlite lib/Files/Storage/Wrapper/QuotaTest.php

Result:

OK, but some tests were skipped!
Tests: 115, Assertions: 506, Skipped: 1.

Manual validation was also performed against an affected Nextcloud instance with S3 primary storage and a finite user quota:

  • Chunked WebDAV upload failed before this patch with 413 Request Entity Too Large / Insufficient space.
  • Applying this one-line change allowed the same chunked WebDAV upload to complete successfully.
  • Previously queued rclone VFS cache uploads were able to proceed without new 413 Insufficient space errors after applying the fix.
  • Backport requested for stable34. I checked stable33, stable32, stable31, and stable30; those branches do not contain the Quota::writeStream() override with the vulnerable $size < $free comparison.

TODO

  • Maintainer review

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@veryCrunchy
veryCrunchy requested a review from a team as a code ownerJuly 1, 2026 20:39
@veryCrunchy
veryCrunchy requested review from ArtificialOwl, Copilot, icewind1991, leftybournes and salmart-dev and removed request for a teamJuly 1, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes false NotEnoughSpaceException failures during quota-wrapped writeStream() writes when the underlying storage reports “unknown/unlimited” free space (negative sentinel), which particularly affects chunked WebDAV uploads to uploads/... on S3 primary storage.

Changes:

  • Update OC\Files\Storage\Wrapper\Quota::writeStream() to allow known-size writes when free_space() is negative (unknown/unlimited), aligning with other quota wrapper write paths.
  • Add a PHPUnit regression test covering a known-size stream write to an uploads/... path when the wrapped storage reports unknown free space.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
lib/private/Files/Storage/Wrapper/Quota.phpTreat negative free_space() as allowed in writeStream() to avoid false “insufficient space” on storages that can’t report free space.
tests/lib/Files/Storage/Wrapper/QuotaTest.phpAdds regression coverage for writing a sized stream to uploads/... when wrapped storage reports unknown free space.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadtests/lib/Files/Storage/Wrapper/QuotaTest.php
@veryCrunchy

Copy link
Copy Markdown
Author

/backport to stable34

@veryCrunchy
veryCrunchyforce-pushed the fix/quota-writestream-unknown-free-space branch from c2fe550 to 93995b1CompareJuly 1, 2026 20:49
@veryCrunchy
veryCrunchy requested a review from CopilotJuly 1, 2026 20:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@susnux

Copy link
Copy Markdown
Contributor

Thank you for your contribution!
Two points regarding the format:

@Mebus

Mebus commented Jul 4, 2026

Copy link
Copy Markdown

I was unfortunately able to reproduce the problem with NC 34.0.1, but was gladly able to fix the issue by applying the proposed patch. Please release this fix as soon as possible :-)

@github-actions

Copy link
Copy Markdown
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@veryCrunchy
veryCrunchyforce-pushed the fix/quota-writestream-unknown-free-space branch from 93995b1 to c019d7cCompareJuly 24, 2026 17:57
@as598466

Copy link
Copy Markdown

Confirming this on a new production instance — same symptoms, same workaround.

Environment

  • Nextcloud Server: <34.0.2>
  • Primary storage: S3 object store (OVH Object Storage, S3-compatible)
  • No totalSizeLimit configured in the objectstore arguments
  • PHP <8.5>, <nginx>, <MariaDB 11.8>

Symptoms

  • User quota set to 5 GB, well under usage. Small files upload fine.
  • Any upload large enough to be chunked (~100 MB and above, and consistently for 1 GB+ files) fails with Insufficient space.
  • Setting the same user's quota to Unlimited makes the exact same upload succeed immediately, with no other change.
  • occ files:scan reports no discrepancy, and occ user:info shows the expected free quota.

Confirmed fix

Changing the single comparison in lib/private/Files/Storage/Wrapper/Quota.php:

 public function writeStream(string $path, $stream, ?int $size = null): int {
// ...
if ($size !== null) {
- if ($size < $free) {+ if ($free < 0 || $size < $free) {
return parent::writeStream($path, $stream, $size);
} else {
throw new NotEnoughSpaceException();
}
}

The root cause analysis in the issue description matches what I see: the chunk parts land under uploads/, which Quota::free_space() delegates to the wrapped storage, and ObjectStoreStorage::free_space() returns FileInfo::SPACE_UNLIMITED (-3) when no total size limit is set. Quota::writeStream() then evaluates $size < -3, which is always false, and throws NotEnoughSpaceExceptionEntityTooLarge / 413.

One thing worth adding for other people hitting this: the regression is not limited to 34.x. I checked the released tags and the Quota::writeStream() override introduced by #59995 is also present in 32.0.13:

So a backport to stable32 looks necessary in addition to stable34.

Assisted-by: Codex:GPT-5
Signed-off-by: veryCrunchy <me@verycrunchy.dev>
@susnux
susnuxforce-pushed the fix/quota-writestream-unknown-free-space branch from 0c279a6 to 2ca04c9CompareAugust 12, 2026 11:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

7 participants

@veryCrunchy@susnux@Mebus@as598466@icewind1991@joshtrichards