Search code examples
shopware6shopware6-api

Find out field in concern regarding FRAMEWORK__WRITE_MALFORMED_INPUT in Shopware 6


Is there a way to find out which field is malformed?

Considering a large constructed array with a lot of data, this message is kinda useless:

{
  "errors": [{
            "status": "400",
            "code": "FRAMEWORK__WRITE_MALFORMED_INPUT",
            "title": "Bad Request",
            "detail": "Expected data to be array.",
            "meta": {
                "parameters": []
            },
            "trace": [{
                        "file": "\/var\/www\/html\/vendor\/shopware\/core\/Framework\/DataAbstractionLayer\/Write\/WriteCommandExtractor.php"
                        ....

The object I'm POSTing to /api/product:

{
    "productNumber": "00000158",
    "stock": 998,
    "price": [
        {
            "net": 5.2857,
            "gross": 6.29,
            "linked": true,
            "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca"
        }
    ],
    "taxId": "0189d01a0a0c73d98d9be2f6e4a4ad0b",
    "manufacturer": {
        "name": "Test Product Manufacturer"
    },
    "manufacturerNumber": null,
    "active": true,
    "shippingFree": false,
    "ean": "",
    "minPurchase": 1,
    "maxPurchase": null,
    "purchaseUnit": null,
    "weight": 0,
    "width": 0,
    "height": 0,
    "length": 0,
    "packUnit": null,
    "deliveryTime": null,
    "name": "Test Product",
    "keywords": null,
    "metaDescription": null,
    "metaTitle": null,
    "description": "",
    "releaseDate": null,
    "updatedAt": "2023-07-04 12:58:04",
    "createdAt": "2022-11-16 17:07:44"
}

I think it's not because of the manufacturer not being in an array, that triggers another exception:

...
"taxId": "0189d01a0a0c73d98d9be2f6e4a4ad0b",
"manufacturer": [
    {
        "name": "Test Product Manufacturer"
    }
],
...

"status":"500","title":"Internal Server Error","detail":"Shopware\Core\Framework\DataAbstractionLayer\Write\DataStack\KeyValuePair::__construct(): Argument #1 ($key) must be of type string, int given

I have then put the manufacturer via GUI into Shopware and it changes my POST query to the following, still throwing MALFORMED exception:

{
    "productNumber": "00000158",
    "stock": 998,
    "price": [
        {
            "net": 5.2857,
            "gross": 6.29,
            "linked": true,
            "currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca"
        }
    ],
    "taxId": "0189d01a0a0c73d98d9be2f6e4a4ad0b",
    "manufacturerId": "0189d56d52bf7356b43f09f511cda17d",
    "manufacturerNumber": null,
    "active": true,
    "shippingFree": false,
    "ean": "",
    "minPurchase": 1,
    "maxPurchase": null,
    "purchaseUnit": null,
    "weight": 0,
    "width": 0,
    "height": 0,
    "length": 0,
    "packUnit": null,
    "deliveryTime": null,
    "name": "Test Product",
    "keywords": null,
    "metaDescription": null,
    "metaTitle": null,
    "description": "",
    "releaseDate": null,
    "updatedAt": "2023-07-04 12:58:04",
    "createdAt": "2022-11-16 17:07:44"
}

Solution

  • I agree that the exception message should be more detailed. This exception is pretty much exclusively thrown when deserializing association type fields. For example you may have a ManyToManyAssociationField with the property name categories. When you want to assign categories, then your payload should look like this:

    {
      "id": "...",
      "categories": [
        {
          "id": "..."
        },
        {
          "id": "..."
        },
        {
          "id": "..."
        }
      ]
    }
    

    However if your payload for the same property is written in the style of a OneToOneAssociationField, e.g. like this...

    {
      "id": "...",
      "categories": {
        "id": "..."
      }
    }
    

    ...that's when that exception will be thrown. Even if you just want to assign a single category for instance, you'll have to provide an array of items, hence why the message reads Expected data to be array.

    As already mentioned it's almost certainly going to be the partial payload of an association that is in an unexpected format. So check those first.

    In your case you're setting deliveryTime to null but it is a property mapped by a ManyToOneAssociationField and as such must be at least an empty array or object.