Davis version
latest
Installation method
Other (describe below)
PHP version (bare metal only)
No response
Database
PostgreSQL
Reverse proxy
Traefik
Authentication method
Internal (ADMIN_LOGIN / ADMIN_PASSWORD)
Affected protocol(s)
Client(s) exhibiting the issue
windows 11 file explorer
Relevant environment variables
Steps to reproduce
add network mount to /dav/public
try to upload a file
Expected behaviour
file uploads
Actual behaviour
"unable to find source"
Logs
Additional context
Quick claude debugging gives:
Add propertystorage (path, name) unique index to a managed DB step
Status: applied manually to the live DB — NOT yet represented in this repo.
What was done
A unique index was created directly on the Davis Postgres database:
CREATE UNIQUE INDEX IF NOT EXISTS propertystorage_path_name_uq
ON propertystorage (path, name);
Run against the CNPG primary:
kubectl -n dav exec baikal-postgresql-1 -c postgres -- \
psql -U postgres -d davis -c \
"CREATE UNIQUE INDEX IF NOT EXISTS propertystorage_path_name_uq ON propertystorage (path, name);"
Why this is needed
WebDAV clients (notably the Windows Explorer mini-redirector) send a PROPPATCH
immediately after every PUT to set Win32CreationTime / Win32LastModifiedTime /
Win32FileAttributes on the just-uploaded file.
Sabre persists those properties via its PDO PropertyStorage backend, which on
PostgreSQL uses an upsert:
INSERT INTO propertystorage (path, name, valuetype, value)
VALUES (:path, :name, :valuetype, :value)
ON CONFLICT (path, name)
DO UPDATE SET valuetype = :valuetype, value = :value;
vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php:148
ON CONFLICT (path, name) requires a unique constraint/index on exactly those
columns. Davis's bundled Doctrine migrations create the propertystorage table
with only a primary key on id — no unique index on (path, name). Postgres
therefore rejects the upsert:
PDOException SQLSTATE[42P10]: Invalid column reference: 7
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
The failing PROPPATCH returns HTTP 500. Windows interprets that as the copy
having failed and rolls back the file it just uploaded — so uploads silently
disappear even though the PUT itself returned 204. (The MySQL/SQLite path uses
REPLACE INTO and relies on the same unique key, so this is Postgres-surfacing a
schema gap that exists regardless of backend.)
Why it isn't in this repo yet
The Davis schema is owned by the container image's own migrations
(doctrine:migrations:migrate, run by the migrations initContainer), not by any
manifest in this Fleet bundle. There is no existing place here to declare DB schema,
so the index was applied out-of-band.
The index lives in the Postgres PVC and survives pod restarts and redeploys. The
risk is only a from-scratch DB rebuild (fresh CNPG bootstrap / restore), which
would recreate the table without it and reintroduce the upload failure.
What to do
Make the index reproducible from git so a DB rebuild can't regress it. Options,
roughly in order of preference:
Until one of the above lands, keep the CREATE UNIQUE INDEX IF NOT EXISTS command
handy — it is idempotent and safe to re-run.
Related context (already committed, for reference)
deployment.yaml command-wrapper adds www-data to a gid-1000 group before
php-fpm starts, so the WebDAV worker can write to the media CephFS dirs
(root:1000). php-fpm's initgroups() discards the pod's supplementalGroups,
which is why the securityContext alone was insufficient. (commit 1751ca9)
Davis version
latest
Installation method
Other (describe below)
PHP version (bare metal only)
No response
Database
PostgreSQL
Reverse proxy
Traefik
Authentication method
Internal (ADMIN_LOGIN / ADMIN_PASSWORD)
Affected protocol(s)
Client(s) exhibiting the issue
windows 11 file explorer
Relevant environment variables
Steps to reproduce
add network mount to /dav/public
try to upload a file
Expected behaviour
file uploads
Actual behaviour
"unable to find source"
Logs
Additional context
Quick claude debugging gives:
Add
propertystorage (path, name)unique index to a managed DB stepStatus: applied manually to the live DB — NOT yet represented in this repo.
What was done
A unique index was created directly on the Davis Postgres database:
Run against the CNPG primary:
Why this is needed
WebDAV clients (notably the Windows Explorer mini-redirector) send a
PROPPATCHimmediately after every
PUTto setWin32CreationTime/Win32LastModifiedTime/Win32FileAttributeson the just-uploaded file.Sabre persists those properties via its PDO PropertyStorage backend, which on
PostgreSQL uses an upsert:
vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php:148ON CONFLICT (path, name)requires a unique constraint/index on exactly thosecolumns. Davis's bundled Doctrine migrations create the
propertystoragetablewith only a primary key on
id— no unique index on(path, name). Postgrestherefore rejects the upsert:
The failing
PROPPATCHreturns HTTP 500. Windows interprets that as the copyhaving failed and rolls back the file it just uploaded — so uploads silently
disappear even though the
PUTitself returned204. (The MySQL/SQLite path usesREPLACE INTOand relies on the same unique key, so this is Postgres-surfacing aschema gap that exists regardless of backend.)
Why it isn't in this repo yet
The Davis schema is owned by the container image's own migrations
(
doctrine:migrations:migrate, run by themigrationsinitContainer), not by anymanifest in this Fleet bundle. There is no existing place here to declare DB schema,
so the index was applied out-of-band.
The index lives in the Postgres PVC and survives pod restarts and redeploys. The
risk is only a from-scratch DB rebuild (fresh CNPG bootstrap / restore), which
would recreate the table without it and reintroduce the upload failure.
What to do
Make the index reproducible from git so a DB rebuild can't regress it. Options,
roughly in order of preference:
Cluster(e.g.managed/postInitSQLor an init script) so the index is created on every fresh bootstrap.
Job(run once after migrations) that executes theCREATE UNIQUE INDEX IF NOT EXISTSabove.drop this workaround once the image includes it.
Until one of the above lands, keep the
CREATE UNIQUE INDEX IF NOT EXISTScommandhandy — it is idempotent and safe to re-run.
Related context (already committed, for reference)
deployment.yamlcommand-wrapper addswww-datato a gid-1000 group beforephp-fpm starts, so the WebDAV worker can write to the media CephFS dirs
(
root:1000). php-fpm'sinitgroups()discards the pod'ssupplementalGroups,which is why the securityContext alone was insufficient. (commit
1751ca9)