Skip to content

Image upload through upload only share leads to NotPermittedException issue while running MetadataUpdate #3252

@powerflo

Description

@powerflo

Describe the bug
Exif extraction fails for image uploaded through upload only share (file drop).

To Reproduce
Steps to reproduce the behavior:

  1. Create public share link with upload only permissions
  2. Upload image with exif metadata through share link
  3. Exif extraction fails (see log message). Photos app shows the image with the filesystem date and not the exif creation date.

Expected behavior
Photos app shows the image with the exif creation date.

Raw log message:

Details

{
    "reqId": "EISu5AjrDHZNEvlwGch4",
    "level": 2,
    "time": "2025-10-24T19:58:17+00:00",
    "remoteAddr": "192.168.21.5",
    "user": "--",
    "app": "no app in context",
    "method": "PUT",
    "url": "/public.php/dav/files/8gcJcbL4Z6BDtqz/1618.jpg",
    "message": "issue while running MetadataUpdate",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0.1 Safari/605.1.15",
    "version": "32.0.0.0",
    "exception": {
        "Exception": "OCP\\Files\\NotPermittedException",
        "Message": "",
        "Code": 0,
        "Trace": [
            {
                "file": "/var/www/html/apps/photos/lib/Listener/ExifMetadataProvider.php",
                "line": 64,
                "function": "fopen",
                "class": "OC\\Files\\Node\\File",
                "type": "->",
                "args": [
                    "rb"
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/ServiceEventListener.php",
                "line": 68,
                "function": "handle",
                "class": "OCA\\Photos\\Listener\\ExifMetadataProvider",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 220,
                "function": "__invoke",
                "class": "OC\\EventDispatcher\\ServiceEventListener",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    },
                    "OCP\\FilesMetadata\\Event\\MetadataLiveEvent",
                    {
                        "__class__": "Symfony\\Component\\EventDispatcher\\EventDispatcher"
                    }
                ]
            },
            {
                "file": "/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 56,
                "function": "callListeners",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    [
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        }
                    ],
                    "OCP\\FilesMetadata\\Event\\MetadataLiveEvent",
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 67,
                "function": "dispatch",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    },
                    "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 79,
                "function": "dispatch",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    "OCP\\FilesMetadata\\Event\\MetadataLiveEvent",
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/FilesMetadata/FilesMetadataManager.php",
                "line": 100,
                "function": "dispatchTyped",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\FilesMetadata\\Event\\MetadataLiveEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/FilesMetadata/Listener/MetadataUpdate.php",
                "line": 42,
                "function": "refreshMetadata",
                "class": "OC\\FilesMetadata\\FilesMetadataManager",
                "type": "->",
                "args": [
                    {
                        "__class__": "OC\\Files\\Node\\File"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/ServiceEventListener.php",
                "line": 68,
                "function": "handle",
                "class": "OC\\FilesMetadata\\Listener\\MetadataUpdate",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 220,
                "function": "__invoke",
                "class": "OC\\EventDispatcher\\ServiceEventListener",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    },
                    "OCP\\Files\\Events\\Node\\NodeWrittenEvent",
                    {
                        "__class__": "Symfony\\Component\\EventDispatcher\\EventDispatcher"
                    }
                ]
            },
            {
                "file": "/var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 56,
                "function": "callListeners",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    [
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        },
                        {
                            "__class__": "Closure"
                        }
                    ],
                    "OCP\\Files\\Events\\Node\\NodeWrittenEvent",
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 67,
                "function": "dispatch",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    },
                    "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                ]
            },
            {
                "file": "/var/www/html/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 79,
                "function": "dispatch",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    "OCP\\Files\\Events\\Node\\NodeWrittenEvent",
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/Files/Node/HookConnector.php",
                "line": 83,
                "function": "dispatchTyped",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->",
                "args": [
                    {
                        "__class__": "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
                    }
                ]
            },
            {
                "file": "/var/www/html/lib/private/legacy/OC_Hook.php",
                "line": 85,
                "function": "postWrite",
                "class": "OC\\Files\\Node\\HookConnector",
                "type": "->",
                "args": [
                    {
                        "path": "/Photos//1618.jpg"
                    }
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Connector/Sabre/File.php",
                "line": 440,
                "function": "emit",
                "class": "OC_Hook",
                "type": "::",
                "args": [
                    "OC_Filesystem",
                    "post_write",
                    {
                        "path": "/Photos//1618.jpg"
                    }
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Connector/Sabre/File.php",
                "line": 360,
                "function": "emitPostHooks",
                "class": "OCA\\DAV\\Connector\\Sabre\\File",
                "type": "->",
                "args": [
                    false
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Connector/Sabre/Directory.php",
                "line": 119,
                "function": "put",
                "class": "OCA\\DAV\\Connector\\Sabre\\File",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/html/3rdparty/sabre/dav/lib/DAV/Server.php",
                "line": 1098,
                "function": "createFile",
                "class": "OCA\\DAV\\Connector\\Sabre\\Directory",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/html/3rdparty/sabre/dav/lib/DAV/CorePlugin.php",
                "line": 504,
                "function": "createFile",
                "class": "Sabre\\DAV\\Server",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/html/3rdparty/sabre/event/lib/WildcardEmitterTrait.php",
                "line": 89,
                "function": "httpPut",
                "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:PUT",
                    [
                        {
                            "__class__": "Sabre\\HTTP\\Request"
                        },
                        {
                            "__class__": "Sabre\\HTTP\\Response"
                        }
                    ]
                ]
            },
            {
                "file": "/var/www/html/apps/dav/lib/Connector/Sabre/Server.php",
                "line": 49,
                "function": "invokeMethod",
                "class": "Sabre\\DAV\\Server",
                "type": "->",
                "args": [
                    {
                        "__class__": "Sabre\\HTTP\\Request"
                    },
                    {
                        "__class__": "Sabre\\HTTP\\Response"
                    }
                ]
            },
            {
                "file": "/var/www/html/apps/dav/appinfo/v2/publicremote.php",
                "line": 150,
                "function": "start",
                "class": "OCA\\DAV\\Connector\\Sabre\\Server",
                "type": "->",
                "args": []
            },
            {
                "file": "/var/www/html/public.php",
                "line": 90,
                "args": [
                    "/var/www/html/apps/dav/appinfo/v2/publicremote.php"
                ],
                "function": "require_once"
            }
        ],
        "File": "/var/www/html/lib/private/Files/Node/File.php",
        "Line": 99,
        "message": "issue while running MetadataUpdate",
        "exception": [],
        "CustomMessage": "issue while running MetadataUpdate"
    },
    "id": "68fbdba2b2a15"
}

Solution
Adding something like that to ExifMetadataProvider.php should fix it:

if (!$node->isReadable()) {
	$event->requestBackgroundJob();
	return;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    0. Needs triagePending approval or rejection. This issue is pending approval.bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions