nextcloud/server · warning · Exception
This addressbook is immutable
Error message
This addressbook is immutable
What it means
Generic PHP Exception thrown by the contactsinteraction 'Recently contacted' address book (an ExternalAddressBook exposed at .../contactsinteraction_recent) from delete(), createFile() and propPatch(). This address book is a read-only, auto-generated view over the recent-contacts table, so every mutating CardDAV operation is deliberately refused; getProperties() even advertises {owncloud}read-only = true.
Source
Thrown at apps/contactsinteraction/lib/AddressBook.php:44
use ACLTrait;
public const URI = 'recent';
public function __construct(
private RecentContactMapper $mapper,
private IL10N $l10n,
private string $principalUri,
) {
parent::__construct(Application::APP_ID, self::URI);
}
/**
* @inheritDoc
* @throws Exception
*/
#[\Override]
public function delete(): void {
throw new Exception('This addressbook is immutable');
}
/**
* @inheritDoc
* @throws Exception
*/
#[\Override]
public function createFile($name, $data = null) {
throw new Exception('This addressbook is immutable');
}
/**
* @inheritDoc
* @throws NotFound
*/
#[\Override]
public function getChild($name): Card {
try {View on GitHub (pinned to ecdeb153ff)
Solutions
- In CardDAV clients, honor the {http://owncloud.org/ns}read-only property and exclude the book from writes/sync
- Direct users to create contacts in a regular (writable) address book — recently-contacted entries are managed by the server
- If the error recurs from a sync client, report it as a client bug (writing to an advertised read-only collection)
- Do not attempt server-side cleanup by deleting this address book; the table is pruned by the contactsinteraction background job
Defensive patterns
Strategy: type-guard
Type guard
// CardDAV client: check the read-only flag before any write
function isReadOnlyAddressBook(\Sabre\CardDAV\AddressBook $book): bool {
$props = $book->getProperties(['{http://owncloud.org/ns}read-only']);
return (($props['{http://owncloud.org/ns}read-only'] ?? false) === true)
|| (($props['{http://owncloud.org/ns}read-only'] ?? 0) === 1);
} Try / catch
try {
$book->createFile($name, $cardData);
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'immutable')) {
// read-only 'Recently contacted' book — route the write to a user address book instead
} else {
throw $e;
}
} Prevention
- Sync clients must honor the advertised read-only property and skip writes to such collections
- Create contacts in regular address books; the recent list is server-managed
- Do not offer delete/rename UI actions on collections flagged read-only
When it happens
Trigger: A CardDAV client issuing DELETE on the address book collection, PUT/POST to create a card inside it, or PROPPATCH on its properties (rename, color) — i.e. any write attempt on the 'recent' address book. Reads (getChildren, getChild, getProperties) succeed; only mutations throw.
Common situations: Sync clients (DAVx5, iOS/macOS Contacts) that try to write cache metadata or reconcile deletions into every synced book; users attempting to delete 'Recently contacted' from the Contacts app; clients that ignore the read-only property and attempt renames.
Related errors
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/d4f27f5450713ff1.
Report an issue: GitHub.