Skip to content

[Bug]: Photos/WebDAV 500 error when metadata value photos-place.value is "Date" #60162

@howanghk

Description

@howanghk

⚠️ This issue respects the following points: ⚠️

Bug description

Nextcloud Photos fails with a 500 error when photo metadata contains a place value of Date.

In my case this was legitimate geolocation-derived metadata: the photos were taken near Date, Iburi Subprefecture, Hokkaido, Japan. Date is a valid place name, but it appears to trigger a PHP TypeError in the DAV property handling path.

After changing the generated metadata value from Date to Hokkaido, the Photos page started working again.

Steps to reproduce

  1. Take a photo near Date, Iburi Subprefecture, Hokkaido, Japan with location data attached to the photo.
  2. Upload the photo to Nextcloud, in my case, it was automatically uploaded with the Nextcloud iOS app
  3. Visit the photos app on Nextcloud, it says "An error occurred"
  4. The underlying DAV request receives a 500 error.

The DAV error message was:

A type error occurred. For more details, please refer to the logs, which provide additional context about the type error.

The server log showed a PHP TypeError similar to:

date() expects at least 1 argument, 0 given

The stack trace referenced DAV property handling, including:

Sabre\DAV\PropFind.php line 95

and the Nextcloud DAV files plugin path that exposes file metadata.

Expected behavior

The Photos page should load normally.

The place name Date should be treated as a normal string value, because it is a valid place name.

Metadata values should not be interpreted as PHP callables when exposed as WebDAV properties.

Nextcloud Server version

32

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.3

Web server

Apache (supported)

Database engine version

PostgreSQL

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

Updated from a MINOR version (ex. 32.0.1 to 32.0.2)

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?

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

Configuration report

{
    "system": {
        "one-click-instance": true,
        "one-click-instance.user-limit": 100,
        "memcache.local": "\\OC\\Memcache\\APCu",
        "apps_paths": [
            {
                "path": "\/var\/www\/html\/apps",
                "url": "\/apps",
                "writable": false
            },
            {
                "path": "\/var\/www\/html\/custom_apps",
                "url": "\/custom_apps",
                "writable": true
            }
        ],
        "appsallowlist": false,
        "check_data_directory_permissions": false,
        "memcache.distributed": "\\OC\\Memcache\\Redis",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "password": "***REMOVED SENSITIVE VALUE***",
            "port": 6379
        },
        "overwritehost": "***REMOVED SENSITIVE VALUE***",
        "overwriteprotocol": "https",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "localhost",
            "***REMOVED SENSITIVE VALUE***"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "pgsql",
        "version": "32.0.8.2",
        "overwrite.cli.url": "***REMOVED SENSITIVE VALUE***",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "maintenance": false,
        "loglevel": "2",
        "log_type": "file",
        "logfile": "\/var\/www\/html\/data\/nextcloud.log",
        "log_rotate_size": "10485760",
        "log.condition": {
            "apps": [
                "admin_audit"
            ]
        },
        "preview_max_x": "2048",
        "preview_max_y": "2048",
        "jpeg_quality": "60",
        "enabledPreviewProviders": {
            "1": "OC\\Preview\\Image",
            "2": "OC\\Preview\\MarkDown",
            "3": "OC\\Preview\\MP3",
            "4": "OC\\Preview\\TXT",
            "5": "OC\\Preview\\OpenDocument",
            "6": "OC\\Preview\\Movie",
            "7": "OC\\Preview\\Krita",
            "0": "OC\\Preview\\Imaginary",
            "23": "OC\\Preview\\ImaginaryPDF"
        },
        "enable_previews": true,
        "upgrade.disable-web": true,
        "mail_smtpmode": "smtp",
        "trashbin_retention_obligation": "auto, 30",
        "versions_retention_obligation": "auto, 30",
        "activity_expire_days": "30",
        "simpleSignUpLink.shown": false,
        "share_folder": "\/Shared",
        "one-click-instance.link": "https:\/\/nextcloud.com\/all-in-one\/",
        "upgrade.cli-upgrade-link": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/2726",
        "updatedirectory": "\/nc-updater",
        "maintenance_window_start": 100,
        "allow_local_remote_servers": true,
        "davstorage.request_timeout": 3600,
        "htaccess.RewriteBase": "\/",
        "dbpersistent": false,
        "auth.bruteforce.protection.enabled": true,
        "ratelimit.protection.enabled": true,
        "files_external_allow_create_new_local": false,
        "trusted_proxies": "***REMOVED SENSITIVE VALUE***",
        "preview_imaginary_url": "***REMOVED SENSITIVE VALUE***",
        "preview_imaginary_key": "***REMOVED SENSITIVE VALUE***",
        "documentation_url.server_logs": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/5425",
        "data-fingerprint": "804ece5c89e12390b553e6f859dd8ed3",
        "updatechecker": false,
        "DOMAIN": "***REMOVED SENSITIVE VALUE***",
        "AIO_VERSION": "v12.9.2"
    }
}

List of activated Apps

Enabled:
  - activity: 5.0.0
  - admin_audit: 1.22.0
  - bruteforcesettings: 5.0.0
  - calendar: 6.2.2
  - circles: 32.0.0
  - cloud_federation_api: 1.16.0
  - comments: 1.22.0
  - contacts: 8.3.8
  - contactsinteraction: 1.13.1
  - dashboard: 7.12.0
  - dav: 1.34.2
  - deck: 1.16.4
  - federatedfilesharing: 1.22.0
  - federation: 1.22.0
  - files: 2.4.0
  - files_downloadlimit: 5.0.0
  - files_pdfviewer: 5.0.0
  - files_reminders: 1.5.0
  - files_sharing: 1.24.1
  - files_trashbin: 1.22.0
  - files_versions: 1.25.0
  - firstrunwizard: 5.0.0
  - logreader: 5.0.0
  - lookup_server_connector: 1.20.0
  - nextcloud-aio: 0.8.0
  - nextcloud_announcements: 4.0.0
  - notes: 5.0.0
  - notifications: 5.0.0
  - notify_push: 1.3.1
  - oauth2: 1.20.0
  - password_policy: 4.0.0
  - photos: 5.0.0
  - privacy: 4.0.0
  - profile: 1.1.0
  - provisioning_api: 1.22.0
  - recommendations: 5.0.0
  - related_resources: 3.0.0
  - richdocuments: 9.0.6
  - serverinfo: 4.0.0
  - settings: 1.15.1
  - sharebymail: 1.22.0
  - support: 4.0.0
  - survey_client: 4.0.0
  - systemtags: 1.22.0
  - tasks: 0.17.1
  - text: 6.0.1
  - theming: 2.7.0
  - twofactor_backupcodes: 1.21.0
  - twofactor_totp: 14.0.0
  - updatenotification: 1.22.0
  - user_status: 1.12.0
  - viewer: 5.0.0
  - weather_status: 1.12.0
  - webhook_listeners: 1.3.0
  - whiteboard: 1.5.7
  - workflowengine: 2.14.0
Disabled:
  - app_api: 32.0.0 (installed 4.0.5)
  - encryption: 2.20.0
  - files_external: 1.24.1
  - files_photospheres: 1.32.0 (installed 1.32.0)
  - maps: 1.6.0 (installed 1.6.0)
  - recognize: 10.0.7 (installed 10.0.7)
  - suspicious_login: 10.0.0
  - twofactor_nextcloud_notification: 6.0.0
  - user_ldap: 1.23.0

Nextcloud Signing status

No errors have been found.

Nextcloud Logs

{"reqId":"wyN9AWIIoVDbKzTiXeOd","level":3,"time":"2026-05-04T17:44:16+00:00","remoteAddr":"***REMOVED SENSITIVE VALUE***","user":"admin","app":"webdav","method":"SEARCH","url":"/remote.php/dav/","scriptName":"/remote.php","message":"date() expects at least 1 argument, 0 given","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36","version":"32.0.8.2","exception":{"Exception":"ArgumentCountError","Message":"date() expects at least 1 argument, 0 given","Code":0,"Trace":[{"file":"/var/www/html/3rdparty/sabre/dav/lib/DAV/PropFind.php","line":95,"function":"date","args":[]},{"file":"/var/www/html/apps/dav/lib/Connector/Sabre/FilesPlugin.php","line":453,"function":"handle","class":"Sabre\\DAV\\PropFind","type":"->","args":["{http://nextcloud.org/ns}metadata-photos-place","Date"]},{"file":"/var/www/html/3rdparty/sabre/event/lib/WildcardEmitterTrait.php","line":89,"function":"handleGetProperties","class":"OCA\\DAV\\Connector\\Sabre\\FilesPlugin","type":"->","args":[{"__class__":"Sabre\\DAV\\PropFind"},{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"}]},{"file":"/var/www/html/3rdparty/sabre/dav/lib/DAV/Server.php","line":1052,"function":"emit","class":"Sabre\\DAV\\Server","type":"->","args":["propFind",[{"__class__":"Sabre\\DAV\\PropFind"},{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"}]]},{"file":"/var/www/html/3rdparty/icewind/searchdav/src/DAV/SearchHandler.php","line":183,"function":"getPropertiesByNode","class":"Sabre\\DAV\\Server","type":"->","args":[{"__class__":"Sabre\\DAV\\PropFind"},{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"}]},{"function":"getPropertiesIteratorResults","class":"SearchDAV\\DAV\\SearchHandler","type":"->","args":[[{"__class__":"SearchDAV\\Backend\\SearchResult","node":{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"},"href":"/files/admin/Photos/26-04-22 20-53-50 7907.jpg"},{"__class__":"SearchDAV\\Backend\\SearchResult","node":{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"},"href":"/files/admin/Photos/26-04-22 20-22-57 7906.jpg"},{"__class__":"SearchDAV\\Backend\\SearchResult","node":{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"},"href":"/files/admin/Photos/26-04-22 15-43-38 7903.jpg"},{"__class__":"SearchDAV\\Backend\\SearchResult","node":{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"},"href":"/files/admin/Photos/26-04-22 15-44-51 7905.jpg"},{"__class__":"SearchDAV\\Backend\\SearchResult","node":{"__class__":"OCA\\DAV\\Connector\\Sabre\\File"},"href":"/files/admin/Photos/26-04-22 15-43-51 7904.jpg"},"And 195 more entries, set log level to debug to see all entries"],["{DAV:}getcontentlength","{DAV:}getcontenttype","{DAV:}getetag","{DAV:}getlastmodified","{DAV:}creationdate","And 21 more entries, set log level to debug to see all entries"]]},{"file":"/var/www/html/3rdparty/icewind/searchdav/src/DAV/SearchHandler.php","line":88,"function":"iterator_to_array","args":[{"__class__":"Generator"}]},{"file":"/var/www/html/3rdparty/icewind/searchdav/src/DAV/SearchPlugin.php","line":119,"function":"handleSearchRequest","class":"SearchDAV\\DAV\\SearchHandler","type":"->","args":[{"{DAV:}basicsearch":{"__class__":"SearchDAV\\XML\\BasicSearch","select":["{DAV:}getcontentlength","{DAV:}getcontenttype","{DAV:}getetag","{DAV:}getlastmodified","{DAV:}creationdate","And 21 more entries, set log level to debug to see all entries"],"from":[{"__class__":"SearchDAV\\XML\\Scope","href":"/files/admin/Photos","depth":"infinity","path":"/files/admin/Photos"}],"where":{"__class__":"SearchDAV\\XML\\Operator","type":"{DAV:}and","arguments":[{"__class__":"SearchDAV\\XML\\Operator","type":"{DAV:}or","arguments":["Encoding skipped as the maximum nesting level was reached"]}]},"orderBy":[{"__class__":"SearchDAV\\XML\\Order","property":"{http://nextcloud.org/ns}metadata-photos-original_date_time","order":"descending"},{"__class__":"SearchDAV\\XML\\Order","property":"{DAV:}getlastmodified","order":"descending"}],"limit":{"__class__":"SearchDAV\\XML\\Limit","maxResults":"200","firstResult":"200"}}},{"__class__":"Sabre\\HTTP\\Response"}]},{"file":"/var/www/html/3rdparty/sabre/event/lib/WildcardEmitterTrait.php","line":89,"function":"searchHandler","class":"SearchDAV\\DAV\\SearchPlugin","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:SEARCH",[{"__class__":"Sabre\\HTTP\\Request"},{"__class__":"Sabre\\HTTP\\Response"}]]},{"file":"/var/www/html/apps/dav/lib/Connector/Sabre/Server.php","line":212,"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":426,"function":"start","class":"OCA\\DAV\\Connector\\Sabre\\Server","type":"->","args":[]},{"file":"/var/www/html/apps/dav/appinfo/v2/remote.php","line":22,"function":"exec","class":"OCA\\DAV\\Server","type":"->","args":[]},{"file":"/var/www/html/remote.php","line":151,"args":["/var/www/html/apps/dav/appinfo/v2/remote.php"],"function":"require_once"}],"File":"/var/www/html/3rdparty/sabre/dav/lib/DAV/PropFind.php","Line":95,"message":"date() expects at least 1 argument, 0 given","exception":[],"CustomMessage":"date() expects at least 1 argument, 0 given"},"id":"69f8dc7690529"}

Additional info

Locating the offending metadata

I found the affected rows with:

SELECT m.file_id, f.path, m.json
FROM oc_files_metadata m
JOIN oc_filecache f ON f.fileid = m.file_id
WHERE m.json::text LIKE '%"photos-place":{"value":"Date"%';

Workaround

Changing the generated place metadata from Date to some other string value fixed the Photos page:

UPDATE oc_files_metadata
SET json = jsonb_set(
    json::jsonb,
    '{photos-place,value}',
    '"Hokkaido"'::jsonb,
    false
)
WHERE json::jsonb #>> '{photos-place,value}' = 'Date';

Suspected root cause

This appears to be caused by Nextcloud passing arbitrary file metadata values directly to SabreDAV’s PropFind::handle() API.

The relevant Nextcloud code path appears to be in apps/dav/lib/Connector/Sabre/FilesPlugin.php, where metadata is exposed as DAV properties:

foreach ($node->getFileInfo()->getMetadata() as $metadataKey => $metadataValue) {
    $propFind->handle(self::FILE_METADATA_PREFIX . $metadataKey, $metadataValue);
}

SabreDAV’s PropFind::handle() accepts either a callback or an immediate value. Internally, it checks whether the second argument is callable. In PHP, a string matching a function name can be callable. Therefore, the metadata value "Date" may be interpreted as the PHP built-in function date() rather than as a literal string property value.

This seems to produce the observed failure:

metadata value: "Date"
    ↓
PropFind::handle(..., "Date")
    ↓
is_callable("Date") === true
    ↓
Date() / date() is invoked with no arguments
    ↓
TypeError: date() expects at least 1 argument, 0 given

Why I think this is a Nextcloud-side bug

SabreDAV’s API intentionally allows handle($propertyName, $valueOrCallback) to receive either a callback or an immediate value.

However, in this case Nextcloud is passing user/generated file metadata directly into that ambiguous API. Since file metadata values can be arbitrary strings derived from EXIF/geolocation/photo metadata, they should be forced to remain data values and should not be allowed to enter the callable path.

Possible fix

One possible fix would be to wrap metadata values in a closure so that SabreDAV sees the closure as the callback and the metadata value itself is returned as plain data:

foreach ($node->getFileInfo()->getMetadata() as $metadataKey => $metadataValue) {
    $propFind->handle(
        self::FILE_METADATA_PREFIX . $metadataKey,
        static fn () => $metadataValue
    );
}

Alternatively, if appropriate for this code path, Nextcloud could use a SabreDAV API that directly sets the property value instead of passing the metadata value through handle().

The important part is that metadata strings such as "Date", "phpversion", "getcwd", etc. should not be interpreted as PHP callable names.

Impact

The confirmed impact in my environment is a persistent Photos/WebDAV failure caused by valid photo place metadata.

This bug class may allow unexpected invocation of zero-argument PHP functions if metadata values match callable function names, depending on how the return value is handled by the DAV response path. At minimum, values matching functions that require arguments can cause a persistent 500 error.

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No fields configured for Bug.

    Projects

    Status

    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions