Description
When using the REST API to set master_picture_attachment on a Part via PATCH, the request always fails with:
"The preview attachment must be a valid picture!"
This happens even when the referenced attachment:
- Has
picture: true in its serialized response
- Has a valid image URL ending in
.jpg
- Was successfully created via
POST /api/attachments with an external image URL
Steps to Reproduce
- Create a part via API:
curl -X POST /api/parts -d '{"name": "Test", "category": "/api/categories/1"}'
# Returns part id=5
- Create an image attachment for the part:
curl -X POST /api/attachments -d '{
"name": "Product Image",
"attachment_type": "/api/attachment_types/1",
"url": "https://assets.lcsc.com/images/lcsc/900x900/20221228_Example_C17414_front.jpg",
"element": "/api/parts/5"
}'
# Returns attachment id=14, "picture": true
- Try to set it as master picture:
curl -X PATCH /api/parts/5 \
-H "Content-Type: application/merge-patch+json" \
-d '{"master_picture_attachment": {"@id": "/api/attachments/14", "_type": "Part"}}'
- Response:
422 - "The preview attachment must be a valid picture!"
Expected Behavior
Since the attachment already exists, has picture: true, and contains a valid image URL (.jpg), setting it as master_picture_attachment should succeed.
Actual Behavior
The Assert\Expression('value == null or value.isPicture()') validation on master_picture_attachment fails.
Root Cause Analysis
The issue appears to be in how API Platform deserializes the @id reference. When processing the PATCH request, it seems to create/load an Attachment object where isPicture() cannot properly evaluate because:
- The
external_path may not be populated on the deserialized object
isPicture() checks hasExternal() then parses the URL extension, but during deserialization the path data may not be available
The validation at src/Entity/Parts/Part.php:164:
#[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')]
protected ?Attachment $master_picture_attachment = null;
calls isPicture() which relies on getExternalPath() returning the URL - but this may be null during the deserialization/validation phase.
Workaround
Currently the only way to set master_picture_attachment is through the Web UI or direct database access (UPDATE parts SET id_preview_attachment=X WHERE id=Y).
Environment
- Part-DB version: latest (Docker image
jbtronics/part-db1:latest)
- PHP 8.x, Symfony, API Platform
- Using SQLite database
Description
When using the REST API to set
master_picture_attachmenton a Part via PATCH, the request always fails with:This happens even when the referenced attachment:
picture: truein its serialized response.jpgPOST /api/attachmentswith an external image URLSteps to Reproduce
422 - "The preview attachment must be a valid picture!"Expected Behavior
Since the attachment already exists, has
picture: true, and contains a valid image URL (.jpg), setting it asmaster_picture_attachmentshould succeed.Actual Behavior
The
Assert\Expression('value == null or value.isPicture()')validation onmaster_picture_attachmentfails.Root Cause Analysis
The issue appears to be in how API Platform deserializes the
@idreference. When processing the PATCH request, it seems to create/load an Attachment object whereisPicture()cannot properly evaluate because:external_pathmay not be populated on the deserialized objectisPicture()checkshasExternal()then parses the URL extension, but during deserialization the path data may not be availableThe validation at
src/Entity/Parts/Part.php:164:calls
isPicture()which relies ongetExternalPath()returning the URL - but this may be null during the deserialization/validation phase.Workaround
Currently the only way to set
master_picture_attachmentis through the Web UI or direct database access (UPDATE parts SET id_preview_attachment=X WHERE id=Y).Environment
jbtronics/part-db1:latest)