Problem/Motivation
Entity browsers do not have an entity type or set of bundles. They are entity type and entity bundle agnostic. Their widgets are often specific to a certain type, such as the file upload widget, or a view widget where there is a certain entity type. Users often think they can use the file upload widget for media and the media upload widget for files. Or they might select an entity browser with a view for users on a node field, and everything works until you go to save and you get an "This entity cannot be referenced" error.
Proposed resolution
Where possible, widgets should expose their entity type and bundle type so that it can be validated against the widget context.
The widgets should be validated on the field widget settings form. If they do not match, a useful error should display to the user.
Additionally, since there may be existing configs, or someone might copy and past within a config, we should have validation when the widget loads to check that it matches the widget context. If it does not match the current context, display to the user a useful error.
A possible follow up would be to get this working on entity embed config form, for example, and inline entity form field widget config form.
Remaining tasks
- review
User interface changes
- additional error messages on the field widget config settings
- replacement of widget with error message if misconfigured within entity browser
API changes
- WidgetBase implements new interface WidgetEntityInfoInterface
- if Widgets implement its methods to expose the widget's entity type or bundle types, additional validation of the widget will take place on the field widget settings and within the entity browser.
Data model changes
- In order to add test coverage of the media_image_upload widget, adding a schema for it (which was missing).
- One thing to note on this is that the 'multiple' parameter is being set to a string even though it *should* be a boolean. This is for backwards compatibility, so as not to break existing implementations.
Original issue summary
Using Drupal 8.4.3 with the new core media module, entity_browser 2.x and media_entity_browser 2.x, when I use the 'Upload images as media items' widget and upload a new image file I get the following error:
The website encountered an unexpected error. Please try again later.
Recoverable fatal error: Argument 1 passed to file_validate() must implement interface Drupal\file\FileInterface, instance of Drupal\media\Entity\Media given, called in modules/contrib/entity_browser/src/Plugin/EntityBrowser/WidgetValidation/File.php on line 31 and defined in file_validate() (line 286 of core/modules/file/file.module).
For example: #2875209: TypeError: Argument 1 passed to file_validate() must implement interface Drupal\file\FileInterface, instance of Drupal\media_entity\Entity\Media given mentions the fix as changing the type of field, however that is not a solution to this problem since the module allows the entity browser to be used for these field types.
| Comment | File | Size | Author |
|---|---|---|---|
| #71 | 2930677-71.patch | 67.81 KB | waropd |
Issue fork entity_browser-2930677
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
rooby commentedComment #3
rooby commentedI know there are a couple of other issues open for the same/similar error however they have been closed and IMO their solutions/workarounds are not sufficient because it is supposed to work with file fields. See:
Comment #4
rooby commentedAs a proof of concept, if I was to change the validate function to do this:
(excuse the potentially bad choice of functions, I'm just hacking stuff out)
Then I get around this issue but then I get "The entity must be of type file. "
That issue has also been reported elsewhere and was fobbed off with the same misconfiguration explanation, however again, if it shouldn't be configured like that we shouldn't be allowing it to be configured like that.
Comment #5
justinlevi commentedI'm also experiencing this issue. Any solution yet?
Comment #6
rooby commentedComment #7
mandavya commentedsame problem here
Any thoughts!
Comment #8
juliakoelsch commentedI migrated to Core Media, and did not alter the config generated during the migration. I have the config as it was generated, and lots of content already, so changing the field type is not an option. Any help would be appreciated!
Comment #9
lias commentedThis is still an issue with core Media and Entity Browser.
Drupal 8.6.1
Entity Browser 8x-2.0
Inline Entity Form 8x-1.0-rc1
Paragraphs 8x-1.3
Unable to upload/replace image using Entity Browser. Clicking on upload does in fact upload the image to sites/default/files/media but doesn't display as uploaded and results instead in "The entity must be of type media." error.
The file displays in the Files content overview section but doesn't register as Media content. The file also shows that it is not used in 0 places.
When switched from Entity Browser widget to Inline entity form - simple/advanced the image is correctly uploaded and displayed.
Similar and unresolved issues:
https://www.drupal.org/project/entity_browser/issues/2822354 - there is a suggested solution to make sure that the field is a Media reference field but I am using entity reference > media > image for the field and still get the "..must be of type.." error
https://www.drupal.org/project/entity_browser/issues/2685029
https://www.drupal.org/project/entity_browser/issues/2948839
------EDIT
I've decide to move to Media Library which is currently experimental in Drupal 8.6.1 core. It seems to be functioning well for selecting media images for reuse and for uploading.
Comment #10
stijndmd commentedYou need to add a reference field instead.
Reference group => Other
Next step: Content group => Media
Next step: in the field setup you can pick one of your created media bundles
Comment #11
oknateremoved comment, I realized it wasn't relevant.
Comment #12
no74hChanging field type is not a solution nor a workaround for sites with uploaded medias. Any ideas?
Comment #13
oknateI believe the bug here is user error. You must use the "Upload" widget for file/image fields and the "Upload as media items" widget for media entity fields.
In order to recreate the bug, I had to use the "Upload as media items" widget on an image field. I don't think this is happening with media entity reference fields.
Feel free to reopen it if you are seeing this using a media entity reference field.
I opened another issue, which is that entity browsers should have an assigned entity type. That way, you could only show relevant widgets for the entity type on the widgets form, and prevent entity browsers for other entity types from showing as options on field widgets.
#3041830: Entity Browsers should be assigned an entity type
Comment #14
rooby commentedI don't really understand why this bug report would be closed and a feature request opened.
This is a bug (a PHP error), which is caused by allowing users to set a broken configuration. Although probably not major since it is not something that happens with the usual configuration.
We should not allow users to do that if it's going to cause errors. At the least we should show a message to say this is an incorrect configuration.
Also, you marked as "Closed (cannot reproduce) in the same comment where you said you reproduced it. If it's going to be closed it should probably be "Closed (won't fix)" or "Closed (works as designed)". Or even "Closed (duplicate)" of that newly created ticket.
Comment #15
oknateGood point, "cannot reproduce" was the wrong designation. We can leave this one open too.
Comment #16
oknateHere's an initial patch that will replace the widget with a warning if wrong entity type widget used on field. Implemented on Upload, MediaImageUpload and View widget.
Comment #18
oknateFixing test and adding entity check and bundle check to EntityForm widget.
Still needs to be done:
Comment #19
oknateAdding validation on the field widget settings form. Since I have another patch that has added some unrelated validation, I worked off a combined patch (with 2807873 #38) . I'm adding a combined patch to test against testbot, and patch that has just the changes for this issue, which could be committed after that one is committed.
- Adds interface WidgetEntityInfoInterface with two methods, ::getTargetEntityTypeId and ::getTargetBundles. I added it to a new interface to avoid breaking BC.
- Adds interface to WidgetBase with default implementations. This way all widgets that extend this class, which should be all of them have default implementations that return NULL or an empty array (for the getTargetBundles()) method. Since the validation checks if these are set before validating, so that contrib modules that extend WidgetBase but haven't implemented the two methods will just not be validated. After this is merged we can create tickets on those other modules issue queues to implement the two methods in their widget classes.
- Updates all four widgets included with module to implement these two methods.
- Add validation to the field widget when settings updated to iterate through the widgets and if the widget has methods that return entity type or bundles, validate them against the field widget settings and set form errors if there is a mismatch.
There are some nice features, such as if a view implements the 'type' filter it will validate that the bundles set in the type filter are within the allowed bundles on the field. This should stop an annoying problem where entity browser allows you to use a view that selects bundles that aren't allowed on field and you get a vague error. See #3035741: Vague error on submit in field widget when invalid item selected.
Still to do:
- add test coverage
Comment #21
oknateAdding test coverage for field widget settings form.
It could still use more test coverage. This covers the functionality, but only tests the view widget. It would be good to test the upload, media upload and entity form widgets.
Comment #23
oknateRequeuing test. It was a random failure.
Comment #24
oknate- Adds test coverage for field widget settings form validation for upload, media upload and entity form.
- Adds schema for MediaUploadWidget, as it was missing, and trying to add it to a test was giving me schema errors. When adding it, I noticed that my configs had been exported with strings for the multiple field, so I changed that one to be a string, so as not to break BC.
- Fixes a bug in my previous patches where the target entity was incorrectly sourced in the validation method.
There is still some test coverage to do. There should be validation for all four widgets when they are misconfigured, it shows the Drupal warning instead of loading the form.
Comment #25
oknateFixing interdiff on the last comment. One of the branches didn't have latest commit.
Comment #26
oknateReroll of patch #24 (as I hadn't merged in changed to one of the branches, so it shows the last commit as part of patch.
Comment #28
oknate- Adds test coverage for all four widgets when misconfigured (which can happen despite field widget validation if they change entity browser after the fact).
- Move similar functionality into widget base, adds new interface for the validation.
To do:
Mostly review. I ran out of time tonight so I might need to fix the tests a little. There might be some cleanup, coding standards. Will look at it with fresh eyes later.
Comment #30
oknateFixing tests.
Comment #31
oknateNow that 2807873 is merged, please review the individual patches, such as
https://www.drupal.org/files/issues/2019-03-25/entity-browser-widget-ent...
Ignore the combined patches.
#2807873: entity browser crashes: 'Used entity browser selection display does not support preselection'
Comment #34
oknateRandom failures on #32, requeuing tests.
Comment #35
rooby commentedAwesome, thanks. I'll try to review ASAP.
Comment #36
oknateReroll
Comment #37
rooby commentedThanks @oknate.
I've got some Drupal contrib time planned for this weekend so I'll review then.
Comment #38
oknatereroll
Comment #39
kellyimagined commentedI went through and tested, and unable to see the error post applying patch from #38.
Comment #40
oknateReroll, as patch wasn't applying any more.
Comment #41
oknateComment #42
kellyimagined commentedThis patches with the latest dev from 4/20, as well as removes the error.
Comment #43
berdirAn issue summary update would be very helpful, explain what exactly the problem is and what the patch is doing. If I understand this correctly, this is basically just about validating which widget can be used in the current context, but it is a pretty massive patch.
Comment #44
oknateComment #45
oknateComment #46
oknateComment #47
oknateComment #48
oknateComment #49
oknateComment #50
oknateSince it's such a massive patch, I broke it up so it can reviewed in parts:
We could possibly break this into 3 patches, if that helps:
They're all interconnected and I feel the changes are relatively low risk, so I think as long it's reviewable, one large patch isn't unworkable.
Comment #51
oknateSame as #40, just reposting.
Comment #52
oknateComment #53
mmbkGreat work, this patch is working fine and really helpful.
While working with the patch, I was wondering whether it is possible to expose only valid entity browsers inside the configuration form. This would make it even easier to configure the form display.
As this patch is already that huge, I don't want to extend it. Nevertheless I tried to implement this functionality and came up with this patch
which might be the base for a possible follow-up?
Comment #54
oknate@mmbk, thanks for the review. I considered limiting the entity browsers in the select, but I was concerned we would get tickets from users concerned that entity browsers are missing from the select. It's too bad drupal core doesn't support greying out select elements. I think we should make a separate issue for this, as a follow up. Perhaps we could add a note under the select. "The following entity browsers are not available to select because they are not applicable to this field widget, @list_of_browsers". We'd also have to handle the case where there are no available entity browsers.
Comment #55
oknateReroll
Comment #56
stewestConfirmed RTBC - Thanks
Comment #57
oknateTested that this still applies against current head. 👍
It will need a reroll against 8.x-1.x branch, as there is a test dependency on drupal:media (>= 8.4)
Comment #58
plato1123 commentedSo for fields that were set up as image (migrated from D7) there's not much hope for ever converting those fields to entity-browser/media, is there?
Maybe we could have some twig trickery where we have a migrated image field AND a new media entity field. If the new media entity field is filled in then the twig just skips rendering the old field. If the new field doesn't exist and the old migrated one does, it shows the old one.
I suppose we could even hide input for the old migrated field so that editors aren't confused by it, if it had content from the migration great, if not nobody would ever know it's even still there.
Or put another way:
field_featured_image_migrated old image field migrated from d7
field_featured_image_media_entity new image field that is entity reference that goes to our media library
If the second one exists then rendering of the first one is ignored, allowing editors to change images for migrated content as they need to (but really they're adding to the new field and the twig is skipping the old one). Maybe a convoluted solution but seems like it would work...
Comment #59
a.dmitriiev commentedI was also thinking how to improve the widget's appearance and found that WidgetBase has access() method. Maybe as another approach it would be better to pass widget_context from form_state (['entity_browser', 'widget_context']) to this access method and then each instance of the widget can decide if it is allowed to be shown or not according to field settings the browser is used in?
Widget Context has 'target_bundles', 'target_entity_type' and 'cardinality'. If widget has restriction by type or bundle it will react on that and restrict access to widget, what do you think?
This will definitely bring some breaking changes to WidgetInterface that doesn't have any arguments for access method.
Comment #60
a.dmitriiev commentedI checked it a bit more and found that it is also possible to not change the access() method definition, because the widget context can be retrieved from entity_browser.selection_storage the same way it is done in src/Plugin/views/filter/ContextualBundle.php starting from line 89 (I am talking about version 2.x)
Comment #61
a.dmitriiev commentedAnother advantage of having this in access() method - when having multiple tabs in the form - the tabs, that should not be there, will not be there, instead of having the message from the patch.
Actually I did the override of the plugin class and extend the access method and it works pretty nice. Maybe this idea could be a part of the existing approved patch?
Comment #62
botanic_spark commented@a.dmitriiev Would you mind sharing your solution? How did you manage to use access method?
I really like the idea of using access() method. It looks much cleaner and natural.
Comment #63
a.dmitriiev commentedFirst I have overriden the widgets:
And then extended the widget classes from entity browser module with the classes listed in the hook above.
EntityFormOverride:
InlineEntityFormMediaWidgetOverride:
MediaEntityDropzoneJsEbWidgetOverride:
WidgetContextTrait:
Comment #64
a.dmitriiev commentedAnd now I have only 1 entity browser that has widgets for all media types, but the tabs are displayed only when they are allowed to be displayed.
Comment #65
botanic_spark commented@a.dmitriiev Nice approach. I ended up patching the access() methods to expose a hook that I can use in other modules.
Then I used my custom module to add logic about widget context, and now I also have a single browser that respects field settings :)
I also like the use of WidgetContextTrait.
Anyway - I think this approach should be considered for this issue as it feels much more user friendly and less misleading then throwing errors and warnings to users.
Comment #66
tobiasbPatch does not apply anymore to latest release https://www.drupal.org/project/entity_browser/releases/8.x-2.10.
Comment #67
hanoiiRe-roll against 2.x
Comment #68
hanoiiFix on the previous re-roll as schema was already there.
Comment #69
nelo_drup commented@hanoii I'm getting this error in drupal 10.2.6 and using paragraphs with an image field with Entity browser widget and use media directories
TypeError: file_validate(): Argument #1 ($file) must be of type Drupal\file\FileInterface, Drupal\media\Entity\Media given, called in /var/www/example.com/modules/contrib/entity_browser/src/Plugin/EntityBrowser/WidgetValidation/File.php on line 31 in file_validate() (line 101 of core/modules/file/file.module).
for some reason the patch doesn't do anything in my case
Comment #70
chris matthews commented2930677-n68.patch in #68 is not working for me either.
Comment #71
waropd commentedPatch on 2.15.0
Comment #72
benstallings commentedClaude Code says:
Issues found:
1. Bug: MediaImageUpload::getForm() breaks the media_type validation. The new if (!empty($widget_context)) wraps the early return, and the existing media_type check is changed to elseif. This means when widget_context IS set but the entity type matches (normal case), the elseif doesn't execute, and media_type validation is completely skipped. The user could have a NULL/invalid media type and the code would fall through without catching it. The existing if for media_type should remain independent, not be chained as elseif.
2. Bug: View widget alter hook receives wrong object. The original code had $view as a ViewExecutable. The refactored code splits it into $view (config entity) and $view_executable, but the alter hook call still passes $view:
$this->moduleHandler->alter('entity_browser_view_executable', $view, ...)This is a breaking change — hook implementations expecting a ViewExecutable now receive a View config entity. Should be $view_executable.3. Unused variable in View widget getForm(). $entity_browser is loaded but never referenced — dead code / wasted query.
4. View loaded 3 times. getForm() loads the view, then getTargetEntityTypeId() and getTargetBundles() each load it again independently. The view object from getForm() should be reused or the results cached.
5. Missing $defaultTheme in WidgetFormValidationTest. All other WebDriverTestBase tests in the module set protected $defaultTheme = 'stark';. This will cause a deprecation warning or test failure on newer Drupal.
6. Missing use statements in EntityReferenceBrowserWidget. The validateSettingsForm references WidgetEntityInfoInterface and FieldConfig, but neither is imported. This would be a fatal error.
7. getTargetBundles() in View widget is fragile but acceptable. It reads $filters['type']['value'] which assumes a specific filter name. Returns [] for unrecognized configurations (fails open), so it won't cause false positives — just missed validations for non-standard views.
8. Bundle validation logic inconsistency. In View widget's getForm(), the bundle check iterates $widget_target_bundles and returns an error if ANY widget bundle is missing from $widget_context['target_bundles']. But this means a view showing articles AND pages would fail validation on a field targeting only articles — even though the view includes articles. Depending on intent, you might want to check for zero overlap rather than requiring all widget bundles to match.
9. Test duplication. testEntityBrowserWidgetContext, testContextualBundle, and testContextualBundleExposed all have identical field setup blocks (creating field_galaxy with the same config). This could use a shared helper like WidgetFormValidationTest::setUpField().
Summary: The feature concept is valuable — catching entity type mismatches at config time saves users from confusing runtime failures. But the patch has two clear bugs (#1 media_type validation bypass, #2 alter hook regression) and a fatal error (#6 missing imports) that need fixing before merge. The performance concern (#4) is secondary but worth addressing.
Comment #73
benstallings commentedComment #75
benstallings commentedComment #77
berdirThis has merge conflicts.
Comment #78
hanoiiI've rebased !142 onto upstream