We are migrating youtube links from D6 link fields to D8 remote video media entities. Prior to that, we successfully migrated a D6 image node-type to image media entities without any issues. The video migration looks like this:

field_media_oembed_video: field_record_source/0/url

The migration fails with this error:

Error: Call to a member function mainPropertyName() on null in Drupal\media\MediaSourceBase->getSourceFieldValue() (line 336 of /var/www/docroot/core/modules/media/src/MediaSourceBase.php).

The underlying problem is that, in MediaSourceBase::getSourceFieldValue() the fields mainPropertyName() method is called even if the field is empty. I am not sure if the problem is really the MediaSourceBase::getSourceFieldValue() method or that the field itself returns the wrong value when it is empty, but I wrote a patch that checks if the field is empty before trying to call the fields mainPropertyName() method.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Nebel54 created an issue. See original summary.

Nebel54’s picture

The last submitted patch, 2: 3059950-1-test-only.patch, failed testing. View results

slv_’s picture

Experiencing this on a site with migrated data where the main source property is not populated. Looks like core should at least check if there's an actual value and:

- a) Return nothing if that's a possible scenario?
or
- b) If it's not a situation that should ever happen, be explicit about it and throw an Exception, so that callers can act on it explicitly.

phenaproxima’s picture

Issue tags: +oembed
phenaproxima’s picture

So here's the thing: no media item is allowed to have an empty source field value.The source field is the one field that, on any given media item, should never be empty. This is a fundamental assumption of the media system.

I think we need to change the approach here. Rather than trying to paper over empty source fields, we need to identify what code path is trying to access an empty source field. So I think the most helpful thing here, for the moment, would be to provide either steps to reproduce the problem, or a backtrace...

seanB’s picture

When the media_entity contrib module was moved to the core media module, the hard requirement was added that media should always have a source field. So it is technically correct that this leads to issues and I agree with phenaproxima that working around the issue is not a good idea. Basically we have a "broken" installation.

Because media_entity in contrib did not have that hard requirement, there are quite a lot of sites out there that have media types without source field. I have seen issues with this in the upgrade path from contrib to core as well. My suggestion would be that we help users fix the "broken" config, instead of helping them work around it.

So we need to:

  1. Provide documentation on how to solve this. Maybe a message in the status report with a link to the documentation?
  2. Provide a drush command in contrib the help users fix it? Not entirely sure how this should work since the source field might not exist yet.
  3. Provide some kind of wizard to help users fix it by letting the choose an existing field or create a new field for media types without a source field.

Most important thing is probably making users aware of this and providing documentation on how to fix it.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

matthieuscarset’s picture

Priority: Normal » Major

I am having this issue with a fresh 8.8.x installation.

Exception is raised when I create a new media with emtpy field_media_oembed_video.

How to reproduce:

  1. Create a new media type
  2. Add the field_media_oembed_video
  3. Mark the field as not required
  4. Create a new media entity with empty value for oembed URL

Result:

The website encountered an unexpected error. Please try again later.
Error: Call to a member function mainPropertyName() on null in Drupal\media\MediaSourceBase->getSourceFieldValue() (line 335 of core/modules/media/src/MediaSourceBase.php). 

I think this is more critical than "a broken installation" (@seanB #7).

We should be able to mark any field as "not required".

Marked this issue as "major".

phenaproxima’s picture

Issue tags: -oembed

We should be able to mark any field as "not required".

Except that, the way the media system is designed, you cannot do this with the source field of a media type. It is not currently enforced in the UI due to complicated technical reasons (there is another issue for that, I think), but it's true. The source field of a media type is always required, and it is not allowed to be made optional, for the reason @seanB outlined in #7. And that's that.

I fully agree that we need to either document this, find a way to automatically fix the broken installations, enforce the "requiredness" of the source field in the UI, or some combination of all of these things. And because it is important to take some course of action on this, I agree with having this issue be marked "major".

But, having said that, making the source field optional is not going to fly. Doing that would contradict the explicit architectural and technical design of the media system and would cause an enormous number of problems, on top of being a major, backwards-incompatible API change.

seanB’s picture

After talking to phenaproxima we agreed on the following (please correct me if I'm wrong).

Existing sites might have a bunch of media items without a source field value. There is not good way to automagically fix that. So for those cases, failing with an exception is bad and for that reason I'm inclined to +1 the improvement in the patch of #2.

Regarding migrations of old sites, it would help very much to have more background on why it would make sense to have a media item without a source value? Same as required node titles, media has a required source field. The source field can contain any value though, depending on the media source. So if needed, sites can always install https://www.drupal.org/project/media_entity_generic or create a custom media source.

Regarding #9. We should not be able to mark any field as not required. The node title or taxonomy term names for example are also always required. The source field for media is just like that. To improve this we should have a followup to probably make it impossible to make a source field non-required, and provide some documentation on why that is.

seanB’s picture

Looking at #2:

+++ b/core/modules/media/src/MediaSourceBase.php
@@ -332,7 +332,10 @@ public function getSourceFieldValue(MediaInterface $media) {
     $field_item = $media->get($source_field)->first();
...
 

Do we really need both $field_item && !empty($field_item)?

Maybe use $media->get($source_field)->isEmpty() instead?

phenaproxima’s picture

Title: OEmbed video migration: Call to a member function mainPropertyName() » Media sources should handle empty source field values more gracefully
FileSize
710 bytes
2.01 KB

Here is a patch which implements the proposed change in #11, with a test.

Since MediaSourceInterface::getSourceFieldValue() already defined a "mixed" return type, I don't think this constitutes an API change. We're just now explicitly documenting, and handling, situations which would previously cause a fatal error.

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

seanB’s picture

Status: Needs review » Reviewed & tested by the community

This looks great to me! Thanks.

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

seanB’s picture

We have a site where users can delete file entities from admin/content/file (for cleanup purposes). Apparently this is also a big issue when a file entity is deleted without deleting the media entity.

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

The last submitted patch, 13: 3059950-13-FAIL.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Discussed with @phenaproxima and @seanB. So the advantage here is that is a migration does result in broken media entities - or a user deletes a file entity directly - then the user can use the UI to fix the media entity. That's a good thing.

One problem with the approach is that errors and the expectation that this is not null is more hidden - so we're not failing as fast which might not be what you want when you're building a migration. We also considered adding logging but this is likely to add up filing the logs very quickly.

@phenaproxima came up with the idea

We could potentially also take advantage of a PHP 7 thing, where these types of errors are (I think) \Throwable. They could be caught, say, by MediaForm and turned into error messages.

seanB’s picture

After some more discussion, we decided we have to accept the reality that media items can have an empty source field value. We don't really want it, but technically this is just something we have to deal with. Some obvious examples:

  • The source field is not required (we strongly encourage site builders to not do this, but it is not enforced).
  • When the source field is an entity reference, the references entity can be removed (a file entity can be deleted).

Since every existing site could technically allow media items with empty source fields, we have decided on the following:

  • Move forward with the current solution on this issue
  • Add some NULL handling to core usages (like \Drupal\media\Plugin\media\Source\OEmbed::getMetadata and \Drupal\media\Plugin\Validation\Constraint\OEmbedResourceConstraintValidator::validate)
  • Probably improve documentation
  • Open follow-up issue to discuss adding som pre or post save logging (opened #3106088: Add logging for media items with empty source field values)
phenaproxima’s picture

Status: Needs work » Needs review
FileSize
4.33 KB
7.19 KB

Okay. Here is a patch which adds explicit NULL handling for the two things in core which use getSourceFieldValue(), plus kernel test coverage.

The last submitted patch, 32: 3059950-32-FAIL.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

seanB’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @phenaproxima. Changes look good to me and the test coverage is pretty thorough. RTBC!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php
@@ -83,6 +83,11 @@ public function validate($value, Constraint $constraint) {
+    // The URL may be NULL if the source field is empty, in which case just
+    // there's nothing more to do.
+    if (empty($url)) {
+      return;
+    }

I'm not sure this is correct. I think we should fail validation if this is the case.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
7.37 KB
4 KB

How's this? I made an empty URL an explicit validation error, and refactored the test so as to do a little less mocking.

seanB’s picture

I made an empty URL an explicit validation error

What happens if users decide to make the source field not required? Would this then fail validation?

alexpott’s picture

@seanB if there is no url then the remote media is invalid. This is only for oembed and in this case I think the URL is truly required.

seanB’s picture

Status: Needs review » Reviewed & tested by the community

The reason I ask is because users can make the field non-required. Which could be confusing. But I guess since this never worked it shouldn't really be a problem.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 36: 3059950-36.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

ravi.shankar’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated test failures, so making it RTBC as per comment #39.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 926087384e to 9.0.x and 58d16a9b5a to 8.9.x. Thanks!

FILE: ...media/tests/src/Kernel/OEmbedResourceConstraintValidatorTest.php
----------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
----------------------------------------------------------------------
 56 | ERROR | [x] Expected 1 blank line before function; 0 found
 62 | ERROR | [x] Expected 1 blank line after function; 0 found
----------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

I fixed these coding standards on commit. Note that anonymous classes don't look fantastic with our coding standards but ho hum...

  • alexpott committed 9260873 on 9.0.x
    Issue #3059950 by phenaproxima, Nebel54, seanB, alexpott: Media sources...

  • alexpott committed 58d16a9 on 8.9.x
    Issue #3059950 by phenaproxima, Nebel54, seanB, alexpott: Media sources...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.