Page MenuHomePhabricator

InvalidArgumentSuggestion in PropertySuggester (action=wbsgetsuggestions) with invalid ID
Closed, ResolvedPublic5 Estimated Story Points

Description

As an API user, I want to be able to make mistakes without crashing anything server-side, in order to experiment with the API easily.

Problem:
If you call the PropertySuggester API with an invalid entity ID, e. g. by accident in the API sandbox, an uncaught exception is thrown

Example:

{
    "error": {
        "code": "internal_api_error_InvalidArgumentException",
        "info": "$idSerialization must match /^Q[1-9]\\d{0,9}\\z/i",
        "errorclass": "InvalidArgumentException",
        "*": "See https://www.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
    },
    "servedby": "mw1290"
}

BDD
WHEN a wbgetsuggestions request with an invalid ID is made
THEN a proper error is returned

Acceptance Criteria 🏕️🌟:

  • Users should not see exceptions for bad input parameters or missing input parameters. Users should see nice error messages.
  • The case of an invalid ID is covered (as in description)
  • The case of no entity param is covered (as in T229319#7180441)
  • Keep an eye out for (and fix if you find) other similar cases in the api parameter validation code)

Event Timeline

You also get an InvalidArgumentException if you simply omit the entity parameter entirely.

https://www.wikidata.org/w/api.php?action=wbsgetsuggestions

{
    "error": {
        "code": "internal_api_error_InvalidArgumentException",
        "info": "Provide either entity-id parameter 'entity' or a list of properties 'properties'",
        "errorclass": "InvalidArgumentException",
        "*": "See https://www.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
    },
    "servedby": "mw1317"
}
Addshore triaged this task as Medium priority.Jun 30 2021, 8:41 AM
Addshore set the point value for this task to 5.

Also https://www.wikidata.org/w/api.php?action=wbsgetsuggestions&properties=a (invalid properties instead of entity)

{
    "error": {
        "code": "internal_api_error_InvalidArgumentException",
        "info": "[a29fc74f-2534-42a3-8a19-910a26cdce23] Caught exception of type InvalidArgumentException",
        "errorclass": "InvalidArgumentException"
    },
    "servedby": "mw2318"
}

Hm, apparently it’s not exactly an uncaught error:

GetSuggestions::execute()
		try {
			$params = $this->paramsParser->parseAndValidate( $extracted );
		} catch ( InvalidArgumentException $ex ) {
			$this->dieWithException( $ex );
		}

I assume this is why the error doesn’t show up in the mediawiki-errors logstash dashboard. But we should still improve this.

So we somehow have to pass the error “properly” into the API module, because throwing an arbitrary exception and then using dieWithException produces these ugly internal errors. (Even if we throw a LocalizedException, the error "code" still looks the same way, though that at least produces a translated message in the "info".) I think there are a few different options:

  • We could use Status objects in more places. A Status is a wrapper around a result and/or error messages of an operation, and then the API can $this->dieStatus( $status ) if there were any errors. I’m not a big fan of Status, but this should work reasonably well. (For SuggesterParamsParser::parseAndValidate(), returning a Status instead of throwing an InvalidArgumentException feels fairly natural in my opinion, but I’m not so sure about SuggestionGenerator’s methods.)
  • We could pass the whole API module into other classes, so that those other classes can use $api->dieWithError(). But that feels pretty ugly, lugging the large API module around everywhere.
  • We could create an ApiErrorReporter and pass that into other classes (similar usage: $errorReporter->dieWithError()). While this still ties those classes to the API, it’s better than passing the whole API module around, and it’s pretty much what we do in Wikibase. However, ApiErrorReporter is a Wikibase Repo class (not a MediaWiki core one), and to me it feels strange to use it in PropertySuggester. On the other hand, PropertySuggester already uses it (exactly once) since T251876.
  • For SuggestionGenerator specifically, we could move more of its code into the API module: it currently throws an InvalidArgumentException if the item or property IDs can’t be parsed, or if the item doesn’t exist. We could move that parsing, and loading the item, into the API module, where we can handle the error better, and then call e.g. SuggestionGenerator::generateSuggestionsByItem() with an Item instead of an $itemIdString. But that also means that the API module grows larger, while SuggestionGenerator would in that case have fairly little code left, to the point where I’m not sure it would still make sense to keep it as a class at all.

Using Status seems most sensible thing here IMHO. It decouples the SuggesterParamsParser and the API module and gives them a shared language to speak.

Change 703745 had a related patch set uploaded (by Lucas Werkmeister (WMDE); author: Lucas Werkmeister (WMDE)):

[mediawiki/extensions/PropertySuggester@master] Declare `continue` as integer parameter

https://gerrit.wikimedia.org/r/703745

Change 703746 had a related patch set uploaded (by Lucas Werkmeister (WMDE); author: Lucas Werkmeister (WMDE)):

[mediawiki/extensions/PropertySuggester@master] Use Status for error handling

https://gerrit.wikimedia.org/r/703746

Change 703745 merged by jenkins-bot:

[mediawiki/extensions/PropertySuggester@master] Declare `continue` as integer parameter

https://gerrit.wikimedia.org/r/703745

Change 703746 merged by jenkins-bot:

[mediawiki/extensions/PropertySuggester@master] Use Status for error handling

https://gerrit.wikimedia.org/r/703746

Addshore subscribed.
{
"error": {
"code": "wikibase-api-invalid-entity-id",
"info": "Invalid entity ID.",
"*": "See https://www.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
},
"servedby": "mw2304"
}