Knowledge base

How the API reports an error

HTTP API error reporting
Code 200 on an error

Two conventions in one node. HTTP submission behaves as expected: an error in the request, the key, the path, the method or inside the node — each gets its own response code, 400, 403, 404, 405 or 500, with details in the errors body.

The configuration API is different: everything except an access refusal returns 200, and the outcome goes into the status field — success or fail — with text in message. A rejected change is not applied.

The refusal text can mislead: deleting a list that is in use may return “no such address list” — the deletion was rejected, and the list stayed in place. And during a large operation, store locking may fail a neighboring operation or an ordinary reload — those are retried.

The main trap is one error handler for both APIs. A client written for submission response codes takes a rejected configuration change for an applied one: the code is 200 there too.
What the Hub does. In the POST /command response the Hub also judges by the status field, not by the code: a command refusal arrives with 200. The Hub does not use the configuration API.
Recommended values

How to tell there was an error:

API Error signal
HTTP submission the response code and the errors body
configuration API status fail and message with code 200
access refusal to the configuration API a response code other than 200
The HTTP submission codes, the configuration API’s 200 with status convention, the misleading text and locking come from the manual (§ 8.1.8–8.1.9, § 8.3, § 8.3.4). The trap analysis is ours.
Example configuration
# a configuration API refusal: code 200, the outcome is in the body
HTTP/1.1 200 Ok
{"message": "Error reading configuration: Config API error: Address 'a@z.com' does not exist in address list 'list1'.", "status": "fail"}
The manual’s example: deleting a nonexistent address is rejected, while the response code is a success.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
How to check on the node
See how a node with the configuration API enabled answers a request for a nonexistent list:
curl -s -w '\n%{http_code}\n' 'http://127.0.0.1:8080/config/address-lists/nosuchlist'
Code 200 with status fail is the configuration API convention: parse the body.
In the Hub
Cost of a mistake
safe: a wrong value breaks nothing
Scenarios
Configuration lifecycle