Skip to content

Removing objects

The delete command removes objects from the server: a domain that is no longer served, a lookup key, a set of test accounts. It destroys one or more objects of a single type, identified by their ids, which usually come from query.

Singletons are the exception. A singleton is an object that exists exactly once on every server, so it cannot be destroyed, only updated, as described in Updating objects.

stalwart-cli delete <object> ( --ids id1,id2,... | --stdin )

The <object> argument is the object type name, with or without the x: prefix. The slash form used to select a variant is rejected. The ids come from exactly one of two sources:

  • --ids: a comma-separated list of ids.
  • --stdin: ids read from standard input.

For a few known objects, the ids are passed on the command line, either a single id or a comma-separated list:

Terminal window
stalwart-cli delete domain --ids xyz789
stalwart-cli delete domain --ids id1,id2,id3

Whitespace around the commas is tolerated, and empty entries are ignored.

When the ids are produced by another command, --stdin reads them from standard input. They can arrive as a JSON array of strings:

Terminal window
echo '["id1","id2","id3"]' | stalwart-cli delete domain --stdin

They can also arrive as a list separated by commas, spaces or newlines:

Terminal window
printf 'id1\nid2\nid3\n' | stalwart-cli delete domain --stdin

Reading from standard input lets the output of query feed a delete directly, so a filter selects the objects and delete removes them. The following pipeline removes every lookup key in the tmp namespace:

Terminal window
stalwart-cli query memorylookupkey --where namespace=tmp --fields id --json \
| jq -r '.id' \
| stalwart-cli delete memorylookupkey --stdin

Each id is deleted on its own, so some can succeed while others fail. The CLI therefore prints one line per id, followed by a summary:

id1 deleted
id2 deleted
id3 failed: error: objectIsLinked
Linked by: <linked objects>
2 deleted, 1 failed

A failed entry reports the JMAP SetError type, which names the reason for the failure. It also lists the linked objects when there are any, and any validation details.

The exit status is 0 when every deletion succeeded and non-zero when at least one failed, so a script can tell whether the whole delete went through. A singleton type is refused before any request is sent, with <Object> is a singleton and cannot be deleted.

The server limits how many objects a single request may change. That limit is maxObjectsInSet, which the CLI reads from the JMAP session and which the maxSetObjects field of the Jmap settings controls. The CLI splits deletions into batches of that size, so a large delete needs no batching by the caller.

A delete most often reports one of these SetError types:

  • objectIsLinked: other objects reference this one. Destroy the linked objects first; the message lists them.
  • notFound: the id does not exist. Confirm the id with query.
  • forbidden: the account lacks the permission for this object type. Authenticate as an account with the required permission.

The objectIsLinked failure is the reason that order matters in a teardown: an object can be deleted only once nothing references it any more. A teardown in which order matters is therefore better done with apply, which processes destroys in reverse plan order and so removes dependent objects before the objects they reference.