MADATA / DEV developer docs Français madata.africa

Errors & retries

A MADATA API error always carries two things: a code, which your program reads, and a message, which a human reads. Knowing which of the two to look at saves a lot of time.

01The XML-RPC shape

A failed call returns a Fault: an integer code and a string. Most libraries raise it as an exception.

pythoncatching a fault
import xmlrpc.client

try:
    models.execute_kw(DB, uid, KEY, 'account.move', 'unlink', [[1042]])
except xmlrpc.client.Fault as f:
    print(f.faultCode)     # 2
    print(f.faultString)   # "warning -- UserError\n\nYou cannot delete a
                           #  posted accounting document."
CodeMeaningWhat to do with it
1Application error. The faultString holds the traceback.Log and alert: this is unexpected.
2Business warning: a rule, a missing value, an incompatible state.The message is meant for a human. Show it as is.
3Access denied: invalid or expired credentials.Replay authenticate once; if it fails again, the key is revoked.
4Insufficient right on the model or the record.Do not retry: this is about permissions, not the network.

02The JSON-RPC shape

In JSON, an error arrives with HTTP 200 and an error key. Checking the HTTP status is therefore not enough: check for error.

jsona JSON-RPC error
{"jsonrpc": "2.0", "id": null,
 "error": {
   "code": 200,
   "message": "Madata Server Error",
   "data": {
     "name": "madata.exceptions.UserError",
     "message": "You cannot delete a posted accounting document.",
     "arguments": ["You cannot delete a posted accounting document."],
     "debug": "Traceback (most recent call last): ...",
     "context": {}
   }}}
FieldWhat it is for
error.code200 application error · 100 session expired · 404 unknown path.
error.data.messageThe message to show. That one, not error.message.
error.data.nameThe error type, as a machine identifier. Use it to decide what to do.
error.data.argumentsThe parts of the message, separated. Handy for custom rendering.
error.data.debugThe technical traceback. Log it, never show it to a user.
The types worth knowing

UserError and ValidationError: a business rule, the message is usable as is. AccessError: a permission is missing. AccessDenied: credentials refused. MissingError: the record no longer exists.

03Common cases

SymptomMost frequent cause
authenticate returns falseDatabase other than prod_<workspace>, or revoked key, or a password used while two factor authentication is on.
"Access denied" on a modelThe key holder does not have the relevant application in their permissions.
An empty list while the screen shows rowsDifferent company scope: pass allowed_company_ids.
A row "missing" after creationIt is archived. Read again with context: {active_test: False}.
"Required field missing"Ask the workspace what it expects: default_get and fields_get.
The call is cut off after a few minutesThe per call duration limit. Paginate or split the work.
503 with Retry-AfterThe workspace is being updated. Wait for the given delay and resume.

04Retrying properly

Three families, three behaviours.

FamilyBehaviour
Transient: 503, dropped network, timeout.Retry, backing off and honouring Retry-After. Past five attempts, alert.
Business: UserError, ValidationError.Never retry as is: the same request gives the same answer. Fix the data, or surface the message.
Permissions: AccessError, AccessDenied.Stop. A retry loop on a revoked key only fills the logs.
Retrying a write is not free

A create cut off by a network timeout may well have gone through on the workspace side. Before replaying a write, look for it: see do not create twice.

05What the response says, and what it does not

Every API response names the platform MADATA: the generic error label is "Madata Server Error", session expiry is "Madata Session Expired", error types are prefixed madata.exceptions., and common.about() returns "Madata. See https://madata.africa". No response names another vendor.

The server_version field is "17.0": that is the version of the call protocol, the one client libraries compare to know how to talk. It does not move from one update to the next and names no brand. The version of your workspace is shown in its settings.

A response that says otherwise

If an API response ever shows you anything but MADATA, that is a defect: report it to support with the exact call and the response you got.

06Logging on the right side

On the workspace side, every write leaves a trace attached to the user holding the key: that is what lets support reconstruct a sequence. On the program side, keep for every failed call the model, the method, the arguments and the full data.debug or faultString. These are exactly the elements you will be asked for, and exactly the ones nobody has when they were not recorded.