nextcloud/server · error · Forbidden
Read-only sharees cannot restore trashbin entries
Error message
Read-only sharees cannot restore trashbin entries
What it means
Restoring a trashed calendar object is only allowed for the owner or, for shared entries, when shared_access is Backend::ACCESS_READ_WRITE — the same canModify() gate as permanent deletion. The restore path is reached by MOVEing the object into the 'restore' target (RestoreTarget::moveInto calls restore()); a read-only sharee gets this Forbidden (HTTP 403) and restoreCalendarObject is never called.
Source
Thrown at apps/dav/lib/CalDAV/Trashbin/DeletedCalendarObject.php:106
}
return $mime;
}
#[\Override]
public function getETag() {
return $this->objectData['etag'];
}
#[\Override]
public function getSize() {
return (int)$this->objectData['size'];
}
#[\Override]
public function restore(): void {
if (!$this->canModify()) {
throw new Forbidden('Read-only sharees cannot restore trashbin entries');
}
$this->calDavBackend->restoreCalendarObject($this->objectData);
}
public function getDeletedAt(): ?int {
return $this->objectData['deleted_at'] ? (int)$this->objectData['deleted_at'] : null;
}
public function getCalendarUri(): string {
return $this->objectData['calendaruri'];
}
public function getSourceCalendarUri(): string {
return $this->objectData['sourcecalendaruri'] ?? $this->objectData['calendaruri'];
}
public function getCalendarPrincipalUri(): ?string {
return $this->objectData['calendarprincipaluri'] ?? null;View on GitHub (pinned to ecdeb153ff)
Solutions
- Run the restore MOVE authenticated as the calendar owner (or owner's calendar-proxy-write)
- Request the owner to grant edit permission on the share so shared_access becomes ACCESS_READ_WRITE
- Filter restore actions client-side using the entry's shared_access/calendarprincipaluri metadata
Example fix
// before: sharee attempts restore via MOVE
$client->request('MOVE', '/remote.php/dav/calendars/bob/trashbin/objects/123.ics', null, [
'Destination' => '/remote.php/dav/calendars/bob/trashbin/restore/123.ics'
]); // 403 for read-only sharee
// after: owner (alice) restores from her own trashbin view
$client->request('MOVE', '/remote.php/dav/calendars/alice/trashbin/objects/123.ics', null, [
'Destination' => '/remote.php/dav/calendars/alice/trashbin/restore/123.ics'
]); Defensive patterns
Strategy: try-catch
Validate before calling
// Same gate as permanent delete: only MOVE-to-restore when allowed
const canModify = (entry) =>
!entry.calendarprincipaluri || entry.shared_access === 2;
if (canModify(entry)) { await restoreViaMove(entry.href); } Try / catch
try {
await client.move(entryHref, restoreHref);
} catch (e) {
if (e.status === 403 && e.message.includes('Read-only sharees')) {
return escalateToOwner(entry); // owner must perform the restore
}
throw e;
} Prevention
- Gate restore buttons on shared_access, mirroring the server's canModify() rule
- For shared calendars, route restore workflows through the owner account
- Test restore flows with a read-only sharee so permission errors surface early
When it happens
Trigger: MOVE of trashbin/objects/<id>.ics to trashbin/restore/<name> performed by a principal with whom the source calendar was shared read-only (calendarprincipaluri set and shared_access not ACCESS_READ_WRITE).
Common situations: A shared team calendar where an editor-with-view-only share tries to recover a deleted event; custom trashbin UIs showing a restore button to every sharee; scripts using sharee credentials for disaster recovery.
Related errors
- Read-only sharees cannot permanently delete trashbin entries
- Permission denied to create files in the trashbin
- Permission denied to create a directory in the trashbin
- Permission denied to delete the trashbin
- Permission denied to rename the trashbin
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/0f638d73a6be994d.
Report an issue: GitHub.