Issue Description
Description
It is not possible to set an address book as default, neither from
the WebUI (the field is read-only) nor via the JMAP API.
Steps to reproduce
- Go to Management > Address Books
- Edit an address book
- The “Default Address Book” field shows
but is not clickable
OR via JMAP API:
curl -X POST https://SERVER/jmap
-H “Content-Type: application/json”
-u “user:password”
-d ‘{
“using”: [“urn:ietf:params:jmap:contacts”],
“methodCalls”: [[
“AddressBook/set”,
{“accountId”: “d”, “update”: {“b”: {“isDefault”: true}}},
“r1”
]]
}’
Response: “Field could not be set” on isDefault
Expected behavior
Being able to define a default address book.
Impact
DAVx5 (Android CardDAV client) fails to synchronize correctly
when no default address book is defined.
Environment
- Stalwart version: 0.16.6
- Client: DAVx5 on Android
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
PostgreSQL
Blob Storage
S3-compatible
Search Engine
Meilisearch
Directory Backend
Internal
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
The root cause is clear from the source code. isDefault is a read-only property on AddressBook – attempting to set it directly in the update object will always return “Field could not be set.” Setting the default address book is done through a separate top-level argument on the AddressBook/set method call, not via the per-object properties.
The correct argument is onSuccessSetIsDefault, which accepts either an existing address book ID or a back-reference to a created ID. Here is a working example:
{
"using": ["urn:ietf:params:jmap:contacts"],
"methodCalls": [[
"AddressBook/set",
{
"accountId": "<your-account-id>",
"update": {
"<addressbook-id>": {
"name": "My Address Book"
}
},
"onSuccessSetIsDefault": "<addressbook-id>"
},
"r1"
]]
}
A few notes:
onSuccessSetIsDefault is a top-level argument on the set method, not a property inside the update patch object. It takes the address book’s ID as its value.
- The
update block still needs to be present (you can include a no-op change like updating the name to its current value, or include a real change alongside it).
- You can also use a creation back-reference (
"#i0") when creating and simultaneously setting a new address book as default.
The WebUI issue (field showing as read-only and non-clickable) is a separate UI gap – the WebUI does not currently expose onSuccessSetIsDefault in its edit form, so using the JMAP API directly (as shown above) is the workaround.
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
isDefault is intentionally a read-only property in JMAP.
The WebUI rendering it as read-only is correct given the schema. The actual
mechanism is the request-level onSuccessSetIsDefault argument on
AddressBook/set: sending it with the address book’s id promotes that book
to the default.