Wikibase APIs use the ApiErrorReporter class to implement some custom error handling. This includes, under the default error format, multiple localized error messages parsed into HTML, all of which you don’t usually don’t get under the default error format (which returns a single error, in plain text, in the site language). The result can look like this (with uselang=de, on an edit blocked by two abuse filters):
{ "error": { "code": "failed-save", "info": "The save has failed.", "messages": [ { "name": "wikibase-api-failed-save", "parameters": [], "html": { "*": "Die Speicherung ist fehlgeschlagen." } }, { "name": "abusefilter-disallowed", "parameters": [ "block edits matching “!AbuseFilter me!”", "4" ], "html": { "*": "Diese Aktion … block edits matching “!AbuseFilter me!”" } }, { "name": "abusefilter-disallowed", "parameters": [ "block edits matching “!AbuseFilter me too!”", "5" ], "html": { "*": "Diese Aktion … block edits matching “!AbuseFilter me too!”" } } ], "*": "See http://localhost/wiki1/api.php for API usage…" } }
This was rather nice at the time (2014, see T47277). However, since then, MediaWiki gained native support for different error formats (including an HTML one), and all except the default “bc” format also support multiple error messages, localized to the request language by default (but configurable using errorlang, if uselang isn’t enough for you) – in other words, all the benefits that ApiErrorReporter once brought to Wikibase can now be enjoyed by all MediaWiki code (since T47843, first shipped in MediaWiki 1.29).
However, Wikibase still carries its custom code. This means that if you specify a different error format, you get a confusing mixture of repeated errors – here’s the same edit as above, but with errorformat=plaintext (as used by Wikibase these days, see T242769):
{ "errors": [ { "code": "failed-save", "module": "wbsetdescription", "*": "Die Speicherung ist fehlgeschlagen." }, { "code": "abusefilter-disallowed", "data": { "abusefilter": {… } }, "module": "wbsetdescription", "*": "Diese Aktion … beizutragen. Kurzbeschreibung der verletzten Regel: block edits matching “!AbuseFilter me!”" }, { "code": "abusefilter-disallowed", "data": { "abusefilter": {… } }, "module": "wbsetdescription", "*": "Diese Aktion … beizutragen. Kurzbeschreibung der verletzten Regel: block edits matching “!AbuseFilter me too!”" }, { "code": "failed-save", "data": { "messages": [ { "name": "wikibase-api-failed-save", "parameters": [], "html": { "*": "Die Speicherung ist fehlgeschlagen." } }, { "name": "abusefilter-disallowed", "parameters": [ "block edits matching “!AbuseFilter me!”", "4" ], "html": { "*": "Diese Aktion … beizutragen.\nKurzbeschreibung der verletzten Regel: block edits matching “!AbuseFilter me!”" } }, { "name": "abusefilter-disallowed", "parameters": [ "block edits matching “!AbuseFilter me too!”", "5" ], "html": { "*": "Diese Aktion … beizutragen.\nKurzbeschreibung der verletzten Regel: block edits matching “!AbuseFilter me too!”" } } ] }, "module": "wbsetdescription", "*": "Die Speicherung ist fehlgeschlagen." } ], "*": "Siehe http://localhost/wiki1/api.php zur Verwendung der API…" }
Note that in the top-level errors, the message is plain text, while inside the wikibase-api-failed-save it’s still HTML. (Plain text has a space after „beizutragen“, in HTML it’s a newline.) If you make a request with different uselang and errorlang, the two copies of the messages will even be in different languages (since Wikibase’s old ApiErrorReporter code has no idea about errorlang).
This situation is, on the whole, confusing, and no longer necessary. We should probably remove all of ApiErrorReporter, or at least all the parts about embedding multiple messages in a single error, and instead just use MediaWiki’s native support for multiple errors. (But make sure to update the corresponding JS code in Wikibase at the same time: we don’t want it to regress towards less specific error messages, as happened in T247690. And if we want to show HTML errors, we should use errorformat=html, not errorformat=plaintext.)