Page MenuHomePhabricator

🐼️ Improve error reporting for PATCH routes
Closed, ResolvedPublic13 Estimated Story Points

Description

As a Wikidata gadget developer I want to know what part of my input caused an error so that I can adjust my code and make successful edits as intended.

The following table summarizes the intended changes to error reports ("error code" and the English error message) in particular situations. WMDE team can find more details, including example input, in the internal working document: https://docs.google.com/spreadsheets/d/1NWvIlCGl23J62Ug08En2Uu-wVRRwx36p-ECZJ6T2fSE/edit#gid=0

Additionally, context field is to be added to error responses on PATCH routes. Its value is a JSON object. In PATCH error responses, error context is supposed to be a JSON Patch object that is relevant for an error.

Descriptioncurrent error (code)Intended error
incorrect JSON patch operationinvalid-patch"code": "invalid-patch-operation"
"message": "Incorrect JSON patch operation: '<op>'"
"context": { "operation": <operation_object> }
invalid field type in JSON patch
(either of op, path, from is not a string)
invalid-patch"code": "invalid-patch-field-type"
"message": "The value of '<field>' must be of type string"
"context": { "operation": <operation_object>, "field": <field> }
missing mandatory field in JSON patch
(op, path, value, also from on copy/move patches)
invalid-patch"code": "missing-json-patch-field"
"message": "Missing '<field>' in JSON patch"
"context": { "operation": <operation_object>, "field": <field> }
Path not found on the resource (statement)cannot-apply-patch"code": "patch-target-not-found"
"message": "Target '<target>' not found on the resource"
"context": { "operation": <operation_object>, "field": <field> }
JSON Patch test operation failedpatch-test-failed"code": "patch-test-failed"
"message": "Test operation in the provided patch failed. At path '<path>' expected '<expected>', actual: '<actual>'"
"context": { "operation": <operation_object>, "actual-value": <actual> }
Removing a required field
Missing required field in the value
patched-statement-invalid"code": "patched-statement-missing-field"
"message": "Missing field '<field>' in the statement data after the changes"
"context": { "patched-statement": <patched_statement>, "field": <field> }
Not allowed value of a fieldpatched-statement-invalid"code": "patched-statement-invalid-value"
"message": "Incorrect value of field '<field>'"
"context": { "patched-statement": <patched_statement>, "field": <field> }
Value does match not the data type of the propertypatched-statement-invalid"code": "patched-statement-value-type-mismatch"
"message": "Value of '<property-id>' does not match property data type after the changes"
"context": { "patched-statement": <patched_statement>, "property-id": <property-id> }

Note: Should finding the data needed for error message or error context turn out to be cumbersome, adjusting those to say something less useful but still helpful is possible. Let's consult if the situation arises.

Update: Crossed out error response changes that are no longer part of this story. See comment from PM.

Related Objects

Event Timeline

WMDE-leszek set the point value for this task to 13.Oct 11 2022, 9:52 AM

Task Breakdown Notes:

  1. T320698: 🐼️ Describe our feature request in a Github Issue to the json-diff library
    • more specific exceptions for various error cases, similar to PatchTestOperationFailedException.php
    • include data that is relevant to the error
  2. T320652: 🐼️ Fork the swaggest/json-diff library
    • general setup: add engineer accounts
    • change composer.json to point to the fork
  3. T320705: 🐼️ Improve JsonPatchValidator to provide more detailed error reports
    • covers both invalid-patch error cases:
      • incorrect JSON patch operation
      • missing mandatory field in JSON patch (op, path, value, also from on copy/move patches)
    • covers everything from Validator to RouteHandler and HttpResponse
  4. T320699: 🐼️ Improve JsonDiffStatementPatcher to provide more detailed error reports
    • covers the cannot-apply-patch error case: "Path not found on the resource (statement)"
    • Note: path information will be needed in the exception
    • covers everything from Patcher to RouteHandler and HttpReponse
  5. T320658: 🐼️ Improve PatchTestOperationFailedException error reports
    • Exception exists, but needs data of:
      • the failed operation
      • the unexpected value that was checked
      • @WMDE-leszek is the actual value expected in the HTTP response's context? If so, what is the key?
    • covers everything from Exception to RouteHandler and HttpReponse
  6. T320706: 🐼️ Handle patch with a missing required field
    • find out if the Deserializer really throws corresponding Exception (if not: find an easy way to make it work or re-negotiate subtask)
    • change StatementDeserializer to catch DeserializationException and:
      • throw our own subclass of DeserializationException in case of a missing required field
      • rethrow otherwise
  7. T320700: 🐼️ Handle patch resulting in a disallowed value of a field
    • find out if the Deserializer really throws corresponding Exception (if not: find an easy way to make it work or re-negotiate subtask)
    • change StatementDeserializer to catch DeserializationException and:
      • throw our own DeserializationException in case of a disallowed value
      • rethrow otherwise
  8. T320659: 🐼️ Improve the InvalidPatchedStatementException thrown in JsonPatcher in case a value does not match the data type of its property
    • find out if SnakValidator reveals the mismatch and the PropertyId (if not: find an easy way to make it work or re-negotiate subtask)
    • create our own Exception as a subclass of InvalidPatchedStatementException
    • determine whether to throw the existing InvalidPatchedStatementException or its new subclass

@WMDE-leszek: how to handle the catch-all exception case, when none of the above apply? What should be used as error code, message and context?
Also: do we really want a single "catch-all"? Doing so, we'd lose some information. Again, we are considering to keep the Exceptions we have for each step of the patching process.

  1. T320708: 🐼️ Make a Pull Request to `swaggest/json-diff` with the changes in our fork
  2. T320709: 🐼️ Handle exceptions that are not explicitly caught yet
    • if applicable
  3. T320710: 🐼️ Add additional `context` field to PATCH errors in the OAS definition
    • add examples

Note on how to arrange work between Gerrit and GitHub:

  1. we create a new branch/pr on the forked library
  2. we create a gerrit patch pointing to the feature branch
  3. when everything looks good, merge the feature branch into the fork's master
  4. point gerrit patch back to depending on the fork's master
  5. merge gerrit patch
Silvan_WMDE renamed this task from Improve error reporting for PATCH routes to 🐼️ Improve error reporting for PATCH routes.Oct 12 2022, 1:14 PM

how to handle the catch-all exception case, when none of the above apply? What should be used as error code, message and context?

Let's stick to current invalid-patch, cannot-apply-patch, patched-statement-invalid and their respective current messages, unless it causes some complications. For context - {patch} for the first two and {patched-statement} for the patched-statement-invalid

Change 845511 had a related patch set uploaded (by Ollie Shotton; author: Ollie Shotton):

[mediawiki/extensions/Wikibase@master] REST: Add optional 'context' to errors

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

Change 845512 had a related patch set uploaded (by Ollie Shotton; author: Ollie Shotton):

[mediawiki/extensions/Wikibase@master] REST: Add optional 'context' field to errors

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

Change 845511 abandoned by Ollie Shotton:

[mediawiki/extensions/Wikibase@master] REST: Add optional 'context' field to errors

Reason:

accidentally created a 2nd patch

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

Change 845619 had a related patch set uploaded (by Ollie Shotton; author: Ollie Shotton):

[mediawiki/extensions/Wikibase@master] REST: Update swaggest/json-diff to v3.10

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

Change 845512 merged by jenkins-bot:

[mediawiki/extensions/Wikibase@master] REST: Add optional 'context' field to errors

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

Change 845619 merged by jenkins-bot:

[mediawiki/extensions/Wikibase@master] REST: Update swaggest/json-diff to v3.10

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

Note: "Removing a required field", "Missing required field in the value", "Not allowed value of a field" are not really patching errors, and handling those will change with T321459: 🌯️ Adjust statement data structure in Wikibase REST API responses and requests, therefore those cases are considered out of scope here and will not be adjusted.

Errors are reported as expected, thank you!