nextcloud / nextcloud/groupfolders

File creation (PUT) fails with 403 Forbidden in Team folders while folder creation (MKCOL) succeeds

Open
#5,107 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage bug
Dominant language
PHP
Stars
343
Forks
106
Avg merge
2d 3h
Merged PRs (30d)
34

Description

Steps to reproduce
  1. Create a fresh Team folder: occ groupfolders:create diag-test-folder
  2. Assign a group with at least read+create rights: occ groupfolders:group <folder_id> admin (permission bitmask confirmed via occ groupfolders:list --output=json; reproduced with bitmask 15 R+U+C+D and 7 R+U+C — same result either way)
  3. Leave Advanced Permissions (ACL) disabled ("acl":false) and quota unlimited ("quota":-3)
  4. Attempt to PUT a small text file directly at the root of the Team folder via WebDAV (/remote.php/dav/files/<user>/<TeamFolder>/test.txt)
  5. Attempt MKCOL at the same location for comparison
Expected behaviour

Both operations succeed (201 Created).

Actual behaviour
  • MKCOL201 Created
  • PUT403 Forbidden, empty exception message, reproducible 100% of the time, at the folder root and inside freshly-created subfolders, on every Team folder tested (including one created purely for this diagnosis).

The exception is thrown at apps/dav/lib/Connector/Sabre/Directory.php:107, inside createFile(), at the $this->fileView->isCreatable($this->path) check — see full trace under Nextcloud log below, which also explains why this diverges from the MKCOL code path.

Server configuration

Operating system: Debian (official nextcloud:apache Docker image), running as an LXC container on Proxmox VE

Web server: Apache 2.4.68 (bundled in the nextcloud:apache image)

Database: MariaDB 11 (mariadb:11 Docker image)

PHP version: 8.5.10

Nextcloud version: 34.0.3.2 (see Nextcloud admin page)

Team folders version: 22.0.6 (latest available at time of writing)

Updated from an older Nextcloud/ownCloud or fresh install: Fresh install (2026-09-06), no upgrade path involved

Where did you install Nextcloud from: Official Docker Hub image (nextcloud:apache), via docker-compose

Are you using external storage, if yes which one: No — data directory is a local bind-mount inside the container, backed by an NFS export on the underlying host (not using the "External storage support" app)

Are you using encryption: No (encryption app disabled)

Are you using an external user-backend, if yes which one: No — Database backend, local accounts only (user_ldap disabled)

Client configuration

Browser: N/A — issue originally observed via the Nextcloud Desktop Client (mirall 34.0.3, Windows), then reproduced and isolated directly over WebDAV using curl (bypassing the desktop client entirely) to rule out client-side causes.

Operating system: N/A (server-side reproduction via curl from the Nextcloud host itself)

Logs
Web server error log
Web server error log
No errors in Apache's error output for the failing requests — only the standard combined-format access log line, e.g.:
172.18.0.1 - admin [DATE] "PUT /remote.php/dav/files/admin/diag-test-folder/test.txt HTTP/1.1" 403 182 "-" "curl/8.14.1"
No PHP warnings/errors/notices logged for this request either (checked via `docker logs`, grepped for php|warn|error|notice|fatal).
Nextcloud log (data/nextcloud.log)
Nextcloud log
{"reqId":"IJezfzekFscLn5rzefhM","level":0,"time":"2026-09-13T14:12:30+00:00","remoteAddr":"REDACTED","user":"admin","app":"webdav","method":"PUT","url":"/remote.php/dav/files/admin/Famille/diag-root-test2.txt","scriptName":"/remote.php","message":"Exception thrown: Sabre\\DAV\\Exception\\Forbidden","userAgent":"curl/8.14.1","version":"34.0.3.2","exception":{"Exception":"Sabre\\DAV\\Exception\\Forbidden","Message":"","Code":0,"Trace":[{"file":"/var/www/html/3rdparty/sabre/dav/lib/DAV/Server.php","line":1098,"function":"createFile","class":"OCA\\DAV\\Connector\\Sabre\\Directory","type":"->"},{"file":"/var/www/html/3rdparty/sabre/dav/lib/DAV/CorePlugin.php","line":504,"function":"createFile","class":"Sabre\\DAV\\Server","type":"->"},{"file":"/var/www/html/3rdparty/sabre/event/lib/WildcardEmitterTrait.php","line":89,"function":"httpPut","class":"Sabre\\DAV\\CorePlugin","type":"->"},{"file":"/var/www/html/3rdparty/sabre/dav/lib/DAV/Server.php","line":472,"function":"emit","class":"Sabre\\DAV\\Server","type":"->"},{"file":"/var/www/html/apps/dav/lib/Connector/Sabre/Server.php","line":215,"function":"invokeMethod","class":"Sabre\\DAV\\Server","type":"->"},{"file":"/var/www/html/apps/dav/lib/Server.php","line":433,"function":"start","class":"OCA\\DAV\\Connector\\Sabre\\Server","type":"->"},{"file":"/var/www/html/apps/dav/appinfo/v2/remote.php","line":25,"function":"exec","class":"OCA\\DAV\\Server","type":"->"},{"file":"/var/www/html/remote.php","line":152,"function":"require_once"}],"File":"/var/www/html/apps/dav/lib/Connector/Sabre/Directory.php","Line":107,"CustomMessage":"Exception thrown: Sabre\\DAV\\Exception\\Forbidden"}}

Directory.php:107 corresponds to:

if (!$this->fileView->isCreatable($this->path)) {
    throw new \Sabre\DAV\Exception\Forbidden();
}

By contrast, Directory::createDirectory() (used by MKCOL, which succeeds) checks $this->info->isCreatable() — a different code path — which returns true.

Browser log
Browser log
N/A — reproduced directly over WebDAV via curl, no browser involved.
Troubleshooting already performed (ruling out configuration/data issues)

To save maintainers time, the following have all been checked and are not the cause:

  • occ groupfolders:list --output=json: group permissions bitmask = 15 (Read+Update+Create+Delete) on the original folder, tested again with 7 (R+U+C) on a brand-new folder — same failure either way.
  • "acl":false, oc_group_folders_acl table empty — Advanced Permissions definitely not in play.
  • Quota: originally found at an invalid -4 (likely leftover from an earlier volume rebuild), corrected to -3 (FileInfo::SPACE_UNLIMITED) via occ groupfolders:quota — no change in behavior.
  • oc_storages.available = 1 for the Team folder storage — not marked unavailable.
  • oc_filecache.permissions = 23 for the folder root (includes Create bit) — cache is not the blocker.
  • Filesystem: www-data can write directly to the underlying directory on disk (confirmed via direct echo/cat inside the app container) — not a filesystem/NFS permission issue.
  • Redis FLUSHALL performed, app container fully restarted (clears APCu/opcache) — no change.
  • occ integrity:check-core and occ integrity:check-app groupfolders both return clean (no output) — app and core files are unmodified/correctly signed.
  • Tested on both the original (September-created) folder and a completely fresh Team folder created during this diagnosis — same failure on both, ruling out folder-specific data corruption.
  • Personal (non-Team-folder) file uploads to the same user's home storage succeed normally (201) on the same instance — issue is specific to Team folder storage.
Additional notes

Happy to provide further debug-level logs, run additional occ diagnostics, or test a patch if one is proposed — this is a fully reproducible, minimal-configuration environment.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with apps/dav/lib/Connector/Sabre/Directory.php:107 and compare createFile()'s fileView->isCreatable() check with createDirectory()'s info->isCreatable() path. Run the reported curl PUT and MKCOL reproduction against a fresh Team folder. Done means uploads return 201 in Team folders while folder creation continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.