HTTP 500 when updating item thumbnail via REST API (get_image_blurhash / Path cannot be empty)

Hi,

I’m integrating Tainacan with an external pipeline that calls the Tainacan REST API, and I’m getting an HTTP 500 error only when updating the thumbnail of items.

Context

  • I’m using Tainacan in a WordPress “aggregator” site.

  • I only use an external pipeline to call the Tainacan/WordPress REST API.

From this external pipeline I:

  1. Create or update Tainacan items using the REST API.
    
  2.  Download an image from an external URL.
    
  3.  Upload that image to **WordPress media** using POST /wp-json/wp/v2/media.
    
  • This returns 201 and a valid attachment_id.
  1. Call PATCH /wp-json/tainacan/v2/items/{item_id} with “_thumbnail_id”: attachment_id to set the thumbnail.

My logs show that the image download and the media upload are working correctly, for example:

Downloading image from: https://repositorio.com/wp-content/uploads/2024/11/MX-Test-001.pdf-cover-scaled.jpg

Attachment successfully uploaded. ID: 4613377

The problem

Right after uploading the attachment and trying to update the item thumbnail, WordPress/Tainacan returns HTTP 500.The REST response includes an error like:

{
  "code": "internal_server_error",
  "message": "<p>There has been a critical error on this website.</p> ...",

  "data": {

    "status": 500,

    "error": {

      "type": 1,

      "message": "Uncaught ValueError: Path cannot be empty in /var/www/html/agregador/wp-content/plugins/***/classes/class-***-media.php:499

Stack trace:

#0 /var/www/html/agregador/wp-content/plugins/***/classes/class-***-media.php(499): file_get_contents()

#1 /var/www/html/agregador/wp-content/plugins/***/classes/repositories/class-***-repository.php(921): Tainacan\\Media->get_image_blurhash()

#2 /var/www/html/agregador/wp-content/plugins/***/classes/repositories/class-***-repository.php(267): Tainacan\\Repositories\\Repository->insert_thumbnail()

#3 /var/www/html/agregador/wp-content/plugins/***/classes/repositories/class-***-repository.php(233): Tainacan\\Repositories\\Repository->insert_metadata()

#4 /var/www/html/agregador/wp-content/plugins/***/classes/repositories/class-***-items.php(236): Tainacan\\Repositories\\Repository->insert()

#5 /var/www/html/agregador/wp-content/plugins/***/classes/repositories/class-***-items.php(491): Tainacan\\Repositories\\Items->insert()

#6 /var/www/html/agregador/wp-content/plugins/***/classes/api/endpoints/class-***-rest-items-controller.php(1000): Tainacan\\Repositories\\Items->update()

#7 /var/www/html/agregador/wp-includes/rest-api/class-wp-rest-server.php(1292): Tainacan\\API\\EndPoints\\REST_Items_Controller->update_item()

...

  thrown",

      "file": "/var/www/html/agregador/wp-content/plugins/***/classes/class-***-media.php",

      "line": 499

    }

  },

  "additional_errors": []

}

So the error comes from Tainacan\Media->get_image_blurhash() calling file_get_contents() with an empty path, which on PHP 8 causes a ValueError: Path cannot be empty.

Relevant plugin code

In class-tainacan-media.php, the get_image_blurhash function (simplified) looks like:

public function get_default_image_blurhash() {

    return apply_filters(

        'tainacan-default-image-blurhash',

        "V4P?:h00Rj~qM{of%MRjWBRjD%%MRjayofj[%M-;RjRj"

    );

}

public function get_image_blurhash($file_path, $width, $height) {

    try {

        if (

            !function_exists('imagecreatefromstring') ||

            !(version_compare(PHP_VERSION, '7.2.0') >= 0) ||

            !$image = @imagecreatefromstring(file_get_contents($file_path))

        ) {

            return $this->get_default_image_blurhash();

        }

        if ($image == false) {

            return $this->get_default_image_blurhash();

        }

        $max_width = 90;

        if ($width > $max_width) {

            $image = imagescale($image, $max_width);

            $width = imagesx($image);

            $height = imagesy($image);

        }

        $pixels = [];

        for ($y = 0; $y < $height; ++$y) {

            $row = [];

            for ($x = 0; $x < $width; ++$x) {

                $index = imagecolorat($image, $x, $y);

                $colors = imagecolorsforindex($image, $index);

                $row[] = [$colors['red'], $colors['green'], $colors['blue']];

            }

            $pixels[] = $row;

        }

        $components_x = 5;

        $components_y = 4;

        $blurhash = \kornrunner\Blurhash\Blurhash::encode($pixels, $components_x, $components_y);

        return $blurhash;

    } catch (\Exception $e) {

        return $this->get_default_image_blurhash();

    }

}

My understanding is:

  • When $file_path is empty (‘’ or null), file_get_contents($file_path) throws a ValueError in PHP 8 (“Path cannot be empty”).

  • That ValueError is not caught, because the catch handles only \Exception, not \Throwable.

  • On older versions this only produced a warning and returned false, so the function would fall back to get_default_image_blurhash() without breaking the request.

Questions

  1. Is there a recommended way to handle this case? For example:
  • validating $file_path before file_get_contents (e.g. empty($file_path) / !file_exists($file_path)) and returning the default blurhash, and

  • changing catch (\Exception $e) to catch (\Throwable $e) to also catch ValueError.

  1. Since I only interact with Tainacan via the REST API from an external pipeline,

is there any configuration or recommended pattern on the REST side to avoid triggering get_image_blurhash() with an empty path, or should this be fixed inside the plugin code?

  1. Are there any hooks/filters around blurhash or thumbnail processing that would allow me to override or wrap this behavior in a separate plugin, so I don’t have to modify the core plugin file and lose changes on updates?

Any guidance or best practices to deal with this situation would be very helpful.

Thank you very much for your time and for any help you can provide.

Hi @erickml
thank you very much for the detailed and straightforward report, it is very helpful for the analysis.

Indeed, the ideal solution is to fix the get_image_blurhash function in the plugin code by updating the try/catch block to catch a \Throwable. This was one of the required changes during the migration to PHP 8 that ended up not being implemented. This block exists precisely to prevent this type of error when no thumbnail has been generated.
If you’d like, you are more than welcome to open a pull request on GitHub with this change, we would be very happy to receive your contribution to the plugin.

The next step is to investigate why the plugin is unable to access the thumbnail path in the following section of the code:

To help with this investigation, could you please test the following request to the Tainacan API, changing the method from PATCH to POST, and check whether the same error is triggered?

curl ‘/wp-json/tainacan/v2/items/[ITEM_ID]’ 
-X POST 
-H ‘Content-Type: application/json’ 
–data-raw ‘{“_thumbnail_id”:[attachment_id]}’

If the error is reproduced in this scenario as well, it will help us better isolate the root cause.

2 curtidas