Skip to content

[Bug]: Recipient can't download/upload in shared folder if their own usage exceeds the owner's quota #65767

Open

Description

@cristianscheid

⚠️ This issue respects the following points: ⚠️

  • This is not a troubleshooting question, general support matter, or webserver/proxy problem, but likely a bug (if unsure, ask the Community Help Forum).
  • This issue is not already reported on Github OR solved at the Community Help Forum (I've searched!).
  • I'm using a maintained major version of Nextcloud Server and tested against the latest patch level. (Supported major versions and current patch levels).
  • I agree to follow Nextcloud's Code of Conduct.
  • I've tried my best to provide clear reproduction steps that someone unfamiliar with this bug could use to reproduce it.

Bug description

When quota_include_external_storage is set to true, recipient can't download or upload in shared folder if their own quota usage exceeds the owner's quota.

Steps to reproduce

  1. start fresh Nexcloud environment (used https://github.com/nextcloud/nextcloud-docker-dev for this)
  2. set quota_include_external_storage to true:
occ config:system:set quota_include_external_storage --type=boolean --value=true
  1. set quota of 50 MB for alice
occ user:setting alice files quota "50 MB"
  1. keep quota unlimited for bob
  2. as alice, create test_folder and place a small PDF file inside
  3. as bob, upload a file greater then alices quota (50 MB +) to it's own files.
    I've downloaded Nextcloud Files Linux Appimage for this (~60 MB):
    https://github.com/nextcloud-releases/desktop/releases/download/v35.0.0/Nextcloud-35.0.0-x86_64.AppImage
  4. as alice, share test_folder with bob
  5. check both users quota and space:
$ occ user:info alice
  - user_id: alice
  - display_name: alice
  - email: 
  - cloud_id: alice@nextcloud.local
  - enabled: true
  - groups:
  - quota: 50 MB
  - storage:
    - free: 23031284
    - used: 29397516
    - quota: 52428800
    - total: 52428800
    - relative: 0.56071311950684
  - first_seen: 2026-10-22T11:43:20+00:00
  - last_seen: 2026-10-22T11:44:24+00:00
  - user_directory: /var/www/html/data/alice
  - backend: Database

$ occ user:info bob
  - user_id: bob
  - display_name: bob
  - email: 
  - cloud_id: bob@nextcloud.local
  - enabled: true
  - groups:
  - quota: none
  - storage:
    - free: 494527238144
    - used: 92572676
    - quota: -3
    - total: 494619810820
    - relative: 0.00018715925641258
  - first_seen: 2026-10-22T11:43:49+00:00
  - last_seen: 2026-10-22T11:43:49+00:00
  - user_directory: /var/www/html/data/bob
  - backend: Database

as can be seen, alice has free space of ~23 MB, bob has way more

With scenario above, recipient (bob) quota usage is greater than owner (alice) quota:

  • recipient (bob) quota usage: ~92 MB
  • owner (alice) quota: ~52 MB

This is a important part to be able to reproduce the issue.

  1. as bob navigate inside test_folder (shared folder)
  2. try to download the PDF file
  • when attempting to download:
Image
  • following exception is thrown:
{
    "reqId": "qLbqIjJrPifUK6WuwxM9",
    "level": 3,
    "time": "2026-10-21T19:34:16+00:00",
    "remoteAddr": "192.168.21.4",
    "user": "bob",
    "app": "webdav",
    "method": "GET",
    "url": "/remote.php/dav/files/bob/test_folder/Nextcloud_Server_Administration_Manual%20(1).pdf",
    "scriptName": "/remote.php",
    "message": "Could not open file: test_folder/Nextcloud_Server_Administration_Manual (1).pdf (118), file does seem to exist",
    "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36",
    "version": "36.0.0.0",
    "exception": {
        "Exception": "Sabre\\DAV\\Exception\\ServiceUnavailable",
        "Message": "Could not open file: test_folder/Nextcloud_Server_Administration_Manual (1).pdf (118), file does seem to exist",
        "Code": 0,
        "Trace": [
            {
                "file": "/var/www/html/3rdparty/sabre/dav/lib/DAV/CorePlugin.php",
                "line": 85,
                "function": "get",
                "class": "OCA\\DAV\\Connector\\Sabre\\File",
                "type": "->",
                "args": []
            },
            {
                "file": "/var/www/html/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
                "line": 89,
                "function": "httpGet",
                "class": "Sabre\\DAV\\CorePlugin",
                "type": "->",
                "args": [
                    {
                        "__class__": "Sabre\\HTTP\\Request"
                    },
                    {
                        "__class__": "Sabre\\HTTP\\Response"
                    }
                ]
            },
            {
                "file": "/var/www/html/3rdparty/sabre/dav/lib/DAV/Server.php",
                "line": 472,
                "function": "emit",
                "class": "Sabre\\DAV\\Server",
                "type": "->",
                "args": [
                    "method:GET",
                    [
                        {
                            "__class__": "Sabre\\HTTP\\Request"
                        },
                        {
                            "__class__": "Sabre\\HTTP\\Response"
                        }
                    ]
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Connector/Sabre/Server.php",
                "line": 216,
                "function": "invokeMethod",
                "class": "Sabre\\DAV\\Server",
                "type": "->",
                "args": [
                    {
                        "__class__": "Sabre\\HTTP\\Request"
                    },
                    {
                        "__class__": "Sabre\\HTTP\\Response"
                    }
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Server.php",
                "line": 435,
                "function": "start",
                "class": "OCA\\DAV\\Connector\\Sabre\\Server",
                "type": "->",
                "args": []
            },
            {
                "file": "/var/www/html/apps/dav/appinfo/v2/remote.php",
                "line": 25,
                "function": "exec",
                "class": "OCA\\DAV\\Server",
                "type": "->",
                "args": []
            },
            {
                "file": "/var/www/html/remote.php",
                "line": 158,
                "args": [
                    "/var/www/html/apps/dav/appinfo/v2/remote.php"
                ],
                "function": "require"
            },
            {
                "file": "/var/www/html/lib/OC.php",
                "line": 1384,
                "function": "{closure:/var/www/html/remote.php:102}",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/html/remote.php",
                "line": 102,
                "function": "handleRequests",
                "class": "OC",
                "type": "::",
                "args": [
                    {
                        "__class__": "Closure"
                    }
                ]
            }
        ],
        "File": "/var/www/html/apps/dav/lib/Connector/Sabre/File.php",
        "Line": 502,
        "message": "Could not open file: test_folder/Nextcloud_Server_Administration_Manual (1).pdf (118), file does seem to exist",
        "CustomMessage": "Could not open file: test_folder/Nextcloud_Server_Administration_Manual (1).pdf (118), file does seem to exist"
    }
}
  1. try to upload a small file (in this case, I've used a file called mock.json, ~3 B):
  • when attempting to upload file "Your have used your space quota and cannot upload files anymore" appears:
Image

Expected behavior

  1. when attempting to download a file, storage free space/quota should not be considered, since file is going to be downloaded to the local machine anyway
  2. when attempting to upload a file, if users have enough free space in quota, uploading the file should work as expected

Actual behaviour

  1. download is not possible and exception is thrown
  2. message indicating that there's no space left in quota, even with both users involved having plenty free space

Nextcloud Server version

36 (master)

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.5

Web server

None

Database engine version

MySQL

Is this bug present after an update or on a fresh install?

Fresh Nextcloud Server install

Are you using the Nextcloud Server Encryption module?

None

What user-backends are you using?

  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other

Configuration report

List of activated Apps

Nextcloud Signing status

Nextcloud Logs

Additional info

No response

Activity

  1. cristianscheid commented on Oct 22, 2026

    @cristianscheid
    MemberAuthor

    I took some time to investigate the code path when running into the download issue:

    • apps/dav/lib/Connector/Sabre/File::get()
    • lib/private/Files/View::fopen() -> basicOperation()
    • apps/files_sharing/lib/SharedStorage::fopen()
    • lib/private/Files/Storage/Wrapper/Quota::fopen() -> free_space()
    // lib/private/Files/Storage/Wrapper/Quota
    #[\Override]
    public function free_space(string $path): int|float|false {
    	if (!$this->hasQuota()) {
    		return $this->getWrapperStorage()->free_space($path);
    	}
    	if ($this->getQuota() < 0 || str_starts_with($path, 'cache') || str_starts_with($path, 'uploads')) {
    		return $this->getWrapperStorage()->free_space($path);
    	} else {
    		$used = $this->getSize($this->sizeRoot); // this line is executed
    		if ($used < 0) {
    			return FileInfo::SPACE_NOT_COMPUTED;
    		} else {
    			$free = $this->getWrapperStorage()->free_space($path);
    			$quotaFree = max($this->getQuota() - $used, 0);
    			// if free space is known
    			$free = $free >= 0 ? min($free, $quotaFree) : $quotaFree;
    			return $free;
    		}
    	}
    }
    • when $used = $this->getSize($this->sizeRoot); line is reached, it calls the following method:
    // lib/private/Files/Storage/Wrapper/Quota
    public function getSize(string $path, ?IStorage $storage = null): int|float {
    	if ($this->quotaIncludeExternalStorage) {
    		$rootInfo = Filesystem::getFileInfo('', 'ext');
    		if ($rootInfo) {
    			return $rootInfo->getSize(true); // this line is executed
    		}
    		return FileInfo::SPACE_NOT_COMPUTED;
    	} else {
    		$cache = is_null($storage) ? $this->getCache() : $storage->getCache();
    		$data = $cache->get($path);
    		if ($data instanceof ICacheEntry && isset($data['size'])) {
    			return $data['size'];
    		} else {
    			return FileInfo::SPACE_NOT_COMPUTED;
    		}
    	}
    }
    • inside method above, when $rootInfo = Filesystem::getFileInfo('', 'ext'); line executes, using xdebug I was able to see that bob's storage is considered, meaning the returned value is quota usage from bob
    • then inside free_space():
      • $quotaFree = max($this->getQuota() - $used, 0);
      • this is were wrong calculation happens:
        • $this->getQuota() is alice quota: ~52 MB
        • $used is bob usage: >52MB
        • this generates free space = 0
    • so this is what was causes the error, comparing bob usage with alice quota

    To fix the part about not being able to download a file, I think a simple solution would be to skip quota/free space check on Quota::fopen() when opening files for reading, since reads don't consume any space:

    This should handle the download part, and it looks good in my tests. However, when uploading a file, neither Quota::fopen() nor Quota::free_space() is executed, so this PR doesn't solve the upload part of the issue.

  2. moved this from To triage to Triaged in 🧑‍🤝‍🧑 Community triageon Oct 22, 2026
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

    0. Needs triagePending check for reproducibility or if it fits our roadmap36-feedbackbug

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions