I need to retrieve an image from an external URL and then save the image on Drupal's file system, and then set the image as the image for a node. In D7, this was a pretty simple task, but it's causing me issues in D8. In D7, here is what we have:

$file_info = system_retrieve_file($url, 'public://course_images/', TRUE);
if(!empty($file_info) && $file_info->fid) {
    $entity->field_image[0] = array('fid' => $file_info->fid);

I am trying the same thing in D8 but just receive this error Value is not valid entity which provides ZERO actual information about exactly what is wrong.

In D8, here is what I currently have:

$file = system_retrieve_file($image_url, 'public://course_images/', TRUE, FileSystemInterface::EXISTS_REPLACE);

if ($file && $file->id) {
  $course_node->set('field_image', [
    'target_id' => $file->id,
    'alt' => 'alt text',
    'title' => 'title'

I've also tried using $file->id() and $file->fid with no luck. I just don't know how to access the file entity id!

I have tried to debug the $file object to figure this out using the logger

Drupal::logger('my_module')->notice('<pre><code>' . print_r($file, TRUE) . '</code></pre>');

but this code is in a cron job and adding that logger just makes the cron job fail with no error other than 'Cron cannot get lock' (again, another error with little to no information).

I can see that my file is being saved properly, but how can I access it's node ID after saving to be able to set as the target_id of the image field?


I moved all this code into an endpoint instead of a cron for debugging purposes. Here is my endpoint:

  function edxServiceTest(Request $request) {
    $course_node = Node::create([
      'type' => 'courses',
      'uid' => 1
    $course_node->set('title', 'Test');
    $course_node->set('langcode', 'en');
    $course_node->set('status', NODE_PUBLISHED);

    $image_url = 'https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Fthewowstyle.com%2Fwp-content%2Fuploads%2F2015%2F01%2Fnature-images.jpg&f=1&nofb=1';

    $file = system_retrieve_file($image_url, 'public://course_images/', TRUE, FileSystemInterface::EXISTS_REPLACE);

    if ($file && $file->fid) {
      $course_node->set('field_image', [
        'target_id' => $file->fid,
        'alt' => 'Alt Text',
        'title' => 'Title',
    } else {
      return new JsonResponse('error', 400);


    return new JsonResponse('success', 201);

Here's what's occurring:

  1. If I try to use $file->id() as the target, the endpoint runs successfully but the node is not added and there is no errors that occur.

  2. If I try to use $file->fid as the target, the endpoint runs into an unexpected error Value is not a valid entity.

  • After set value field_image, you have to save node $course_node->save();
    – Jonh
    Commented Nov 20, 2020 at 4:08
  • Do you get an error when you access $file->id() or $file->fid, or do you think that isn't the correct way to get the file ID (which isn't its node ID) because using $file->id() as target ID causes any error?
    – apaderno
    Commented Nov 20, 2020 at 9:14
  • As it happens for every entities, $file->id() returns its ID. With file entities, it's possible to get the same value with $file->fid. Only id() is exposed from FileInterface; when a method/function returns an object implementing FileInterface, id() is safer to use, as an object implementing that interface doesn't necessarily have any fid property.
    – apaderno
    Commented Nov 20, 2020 at 9:53
  • As for the value an image field accepts for the target_id property, that is the ID of a file entity. Replace $file->id with $file->id(), and the code should work. If it doesn't work, the error is in another place.
    – apaderno
    Commented Nov 20, 2020 at 9:56
  • @Jonh I am saving the node, I only put in the portion of the. ode relevant to the question.
    – BlondeSwan
    Commented Nov 20, 2020 at 15:20


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.