Problem/Motivation
PHP 8.1 has deprecating passing NULLs to many string manipulating functions. This can cause contrib tests to fail with:
htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated.
This is due to FormattableMarkup replacements being null - those go straight as nulls down to Html::escape() and hence to htmlspecialchars(), where PHP 8.1 complains.
Proposed resolution
The PHP deprecation can be really hard to debug because you don't get a stack trace. Therefore, this issue adds a deprecation to FormattableMarkup that tells you which string and argument key is causing the problem.
Remaining tasks
None
User interface changes
None
API changes
Html::escape and Html::decodeEntities are typehinted to return string. This is okay because these are static functions.
Data model changes
None
Release notes snippet
Passing a NULL value as a placeholder value to translatable markup or formattable markup is deprecated and will cause an exception in Drupal 11.
| Comment | File | Size | Author |
|---|---|---|---|
| #127 | 3255637-10.x-127.patch | 6.73 KB | alexpott |
| #127 | 125-127-interdiff.txt | 1.21 KB | alexpott |
| #125 | 3255637-10.x-125.patch | 6.76 KB | alexpott |
| #125 | 122-125-interdiff.txt | 5.76 KB | alexpott |
| #122 | 3255637-10.x-122.patch | 6.66 KB | alexpott |
Issue fork drupal-3255637
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
mondrakeTest only and fix patches.
Comment #3
mondrakeAhem.
Comment #6
hswong3i commentedI face this issue when working with search_api_solr reindexing + PHP 8.1.
MR created for 9.4.x-dev
Comment #8
liam morlandRebased. No functional change except that if NULL is passed to placeholderEscape(), Html::escape() will get empty string instead of NULL. Includes test.
Comment #9
neclimdulPatch review, this should avoid the call to escape on null and just return the empty string.
Regarding the approach, I'm not sure this is correct. Should we allow null? The documentation on the method is very explicit
"a string or an object that implements \Drupal\Component\Render\MarkupInterface" and the examples go into quite a bit of detail to show how to make it a safe string or Markup.
Additionally, something passing null is probably hitting an unrealized bug. That's kinda the reason PHP deprecated these null string conversions.
Side note: pretty sure deprecation notices aren't major, just normal. Users shouldn't see them since we expect deprecation errors to be off except for development and testing.
Comment #10
liam morlandWould a suitable solution be to check the type of
$valueand if the type is wrong, run something like the following?Comment #11
neclimdulCould be. It feels weird adding a deprecation... to a deprecation? Maybe that's the correct approach to set our own timeline though?
Comment #12
liam morlandFor now, perhaps it's fine as it is and contrib needs to be updated to not send NULL to this function.
Once we require PHP 8.1, we can add a type declaration using union types. That would make it easier to find where this is being called with the wrong type.
Comment #13
andypostComment #14
liam morlandPerhaps this should be included in a broader issue about adding type declarations.
Comment #15
rossidrup commentedI get this error
Deprecated function: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in Drupal\Component\Utility\Html::escape() (line 424 of core/lib/Drupal/Component/Utility/Html.php).
Comment #16
sgourebi commentedFix for issue that happens on Drupal 9.3 with PHP 8.1 :
Deprecated: htmlspecialchars(): Passing null to parameter #1($string)of type string is deprecated in core/lib/Drupal/Component/Utility/Html.php
Comment #17
rossidrup commented16# solved the problem.... I just replaced the lines in that file manually. Will I have to redo it again after upgrading to newer version of core? Will the file get overwritten?
Comment #18
ankithashettyYes, @rossidrup. You will have to redo it after upgrading. But, manually editing core/contrib module code is not the right way.
The recommended way is to use
cweagans/composer-patchesand applying patch through composer. You can checkout this doc for more info: https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies#patches.Thanks!
Comment #19
rossidrup commentedI see, but why does this error happen and why do they don't they hard code the patch into the next release? Does it happen only on some sites? What is the reason? I do not understand...
I could only see this error when I went to my adaptive theme settings, on bartik the error does not show up....
also it does not show up on other drupal installations that use same adaptive theme and there is no error...
Comment #21
liam morlandThis new merge request adds the type declarations.
Comment #22
liam morlandThis is a similar issue for Drupal 9.3. It does not depend on union types, so it could go in right away. Review would be appreciated.
Comment #23
3liAdding the type declarations seems like the correct way to go, however it will also change this issue from a warning to
TypeError.Stack trace:
So for now the solution seems easier use to #16 or MR 1659
Comment #24
liam morland@#23: Yes, I agree that type declarations are the best solution.
Perhaps in FormattableMarkup.php on line 208 and 232, where
placeholderEscape()is called, it should check for NULL at that point or cast$valueto string.Comment #25
3liThen based upon MR 2040, this patch checks for null going into
placeholderEscape()Comment #26
3liRe-roll to correct full paths, for running tests.
Comment #27
liam morland@3li: Thanks. You could also click on "get push access" and then push your addition to the existing merge request.
??will work. It could also be?:.Maybe it would be better if it was:
This way there is never an empty
emelement.Comment #28
devitate commentedusing #26 I get this from the LinkGenerator
If I remove the type declaration it works
Comment #29
liam morlandIt sounds like you are not running PHP 8.1. That is why the same error does not come up when NULL is passed to
htmlspecialchars(). The purpose of the type declaration is to identify places where NULL is sent toHtml::escape()so that those can be fixed.Comment #30
3liPatch based upon the current MR.
Have added a checks to prevent passing null to escape while generating URL like in #28.
Comment #32
neclimdul#23 was mistaken about ?: and its causing a _lot_ of failures. For example it is failing by converting 0 into an empty string in the bytes test. We specifically want to null coalesce and only act on null values, not check the truthyness of the input.
Comment #33
liam morlandYes, I see. This also not right, since it would return empty string if
$valueis 0.It should be:
Comment #34
ravi.shankar commentedMade changes as per comment #33.
Comment #35
3liUpdated MR - tests are now passing.
Comment #37
martijn de wit"Merge blocked: the source branch must be rebased onto the target branch." tried to rebase the issue branch
Comment #38
lapurddrupal commentedThanks guys, works, no more errors now . D 9.3.15, PHP 81.3 , 10.5.15-MariaDB.
Comment #39
buuza commentedHi All,
I have a similar issue when indexing search, but in my case it passing an array:
My stack is Drupal 9.3.15, PHP 8.1 and MariaDB 10.3.34
Do you have any suggestions to fix it?
I'm upgrading it from Drupal 9.2.20 and php 7.4
Thank you
here is traceback:
Comment #40
3li@buuza have you tried to apply any of the patches?
Though it is also possible this issue is coming from
search_apibased upon your stack trace.Comment #41
buuza commentedHi @3li,
Yes, I did apply patch #16 which fixed errors and search index is working again.
Also, we found the issue with Argument #1 ($string) must be of type string, array given in htmlspecialchars() - it was twig templates passing arrays.
thanks
Comment #42
rivimeyI tried patch -34 but this has a bug:
Uncaught TypeError: Argument 1 passed to Drupal\Component\Render\FormattableMarkup::placeholderEscape() must implement interface Drupal\Component\Render\MarkupInterface, string given, called in /var/www/html/web/core/lib/Drupal/Component/Render/FormattableMarkup.php on line 232 and defined in /var/www/html/web/core/lib/Drupal/Component/Render/FormattableMarkup.php:262
The problem is that placeholderEscape is defined as accepting *only* a MarkupInterface,
protected static function placeholderEscape(MarkupInterface $value): string {
but it's param doc:
* @param string|\Drupal\Component\Render\MarkupInterface $value
and its code:
return $value instanceof MarkupInterface ? (string) $value : Html::escape($value);
..expect that it can be passed a string value, which is what happened for my error.
The right fix for now is I think to remove MarkupInterface from the type spec, because IIRC the php version that supports variant-type parameters is newer than the minimum for D9.
Comment #43
rivimeyThis is a patch in which the one change mentioned above has been made.
Comment #45
martijn de wit@rivimey can you try to use the merge request from this issue ?
Comment #46
liam morlandThis can use union types for type declarations. Example:
Comment #48
jamesoakleyPatch at #16 works for me too.
Is this targetting 10.0.x-dev only because bugs get squashed for Drupal 10 first before being backported to Drupal 9? I'm simply running 9.4.3 in production and hit this when I updated to use PHP 8.1 ready for Drupal 10 (when PHP 8.0 support will be dropped).
Comment #49
rivimey@martijn-de-wit just to confirm, yes I did manage to apply the merge patch and it's ok now with php8.
The backport to D9 will need to remove the union types... current D9.4's composer requires { "php": ">=7.3.0" }" whereas php 8 is required for union types.
Comment #50
jamesoakleyWhy does the simpler approach in the patch at #16 not work correctly? It bypasses any need to use union types, and so gives a solution that works for all currently supported versions of Drupal core.
Comment #51
liam morlandThe fix in #16 would work, but it doesn't solve the underlying problem of code that sends non-strings into this function. This issue is against Drupal 10, which only runs on versions of PHP that support union types anyway.
Comment #52
rivimeyLiam, IMO it would simplify a lot of code if this function were to accept null as well as string and markup objects. I agree it shouldn't be accepting other things (int, for example?). Return value for input=null should IMO be "".
Comment #53
liam morlandThis is covered in comment #9. Perhaps a maintainer needs to make a decision. It either needs a type declaration which matches the documentation or appropriate casting inside the function.
This is the same basic question as #3271517: Add type declarations to Html::decodeEntities() and Html::escape().
Comment #54
jamesoakleyLiam, if this issue is specifically related to Drupal 10's support of union types, does that mean that I should open a fresh issue if I'm seeing the same error on a Drupal 9 site using PHP 8.1?
Comment #55
liam morlandUsually issues are fixed in the development version and then backported. In this case, the best fix uses union types, so the fix would likely be different for version before Drupal 10. So, making another issue would be a reasonable step.
Comment #56
neclimdulOn #3271517: Add type declarations to Html::decodeEntities() and Html::escape() @borisson_ brings up concerns of this being a BC break. I kinda agree. Today tests fail because we treat unexpected deprecation as errors but sites continue to function. This patch flips that and its always a fatal error breaking sites.
The problem with these two issues is Drupal needs to communicate changes while continuing the intent of a thin wrapper around the PHP methods. That's kinda unique because of how this class is designed but also pretty similar to a lot of other PHP 8.1 and 8.2 issues floating around the queue. <rant></rant>
As I noted in #11, it feels very weird to add a deprecation that effectively wraps a PHP deprecation. Putting the gut reaction aside, the fact is it separates PHP's deprecation timeline from our deprecation timeline. That means it is probably the right decision for the reasons @borisson_ mentions.
That said, depending on how fast this moves and maintainer buy in, that path might make the interface change _faster_ than PHP's because these changes could land in 9.5 and and interface change 10 meeting the "10 is 9 - deprecation" promise.
Comment #57
neclimdulHere's a 9.5 deprecation patch to see where it goes.
Comment #58
ravi.shankar commentedFixed Drupal CS issue of patch #57.
Comment #59
liam morlandThis issue is targetting 10.0.x but the latest patch says "deprecated in drupal:9.5.0 and is removed from drupal:10.0.0".
Comment #60
rivimeyLiam, the new trigger_error talks of the 'passing of null' being deprecated, not the whole routine.
I must admit, though, I find the wording ambiguous... what exactly does 'is removed from' mean? I think it would be clearer if it became 'will cause a php Error' or similar.
Comment #61
liam morlandOK, I see. It is not that something gets removed, but that the required PHP upgrade causes the error to happen.
Comment #62
maxilein commentedPatch #58 applied to 9.4.5 and seems to be working. I had multiple errors on the extend page.
They are gone now.
Comment #63
longwaveIt is too late to add this to 9.5.x or 10.0.x, this will have to go into 10.1.x for removal in 11.0.x now.
Comment #64
liam morlandComment #65
ravi.shankar commentedAddressed comment #63.
Comment #67
liam morlandPerhaps "is removed from" should instead be "is prohibited starting in".
Comment #68
pradhumanjain2311 commentedAddressed comment #67.
Comment #69
robcarrI realise that this issue is now focussed on 10.1.x but the patch at #68 applied to 9.4.8 and has stopped the deprecation errors flagging up
Comment #70
aaronpinero commentedI have observed a very similar issue when updating a Drupal 9.4.8 website to use PHP 8.1 (moving from PHP 7.4). After updating to PHP 8.1, if I visit the "Available Updates" page in the Drupal admin (/admin/reports/updates), the dblog becomes littered with php debug messages. The stack trace is:
Applying the patch from #68 to Drupal core seems to stop these messages from accumulating in the dblog.
Comment #71
rivimeyI am loath to suggest changing this, as this issue has gone on far too long.
However, "prohibited" is not in my opinion the best option here. I would prefer "trigger a PHP error from", as in:
...deprecated in drupal:10.1.0 and is prohibited starting in drupal:11.0.0. Pass a string or ...becomes:
...deprecated in Drupal:10.1.0 and will trigger a PHP error, starting from Drupal:11.0.0. Pass a string or ....This updated version of the patch is attached. I've also changed 'drupal' to 'Drupal' -- proper names have capital letters.
We also need to address the problem of Drupal 9 sites running with php8.1, which will be the normal state soon if not now, and do so quickly. Dropping lots of stack traces into the system log is not a good look!
At least at present, the existing patch 3255637-68.patch nearly applies cleanly to HEAD of 9.5.x (f3a8b0dadc4). I have uploaded a version that does apply cleanly, using extension "nopatch" because this issue is versioned for D10!
Comment #72
rivimeyMarking Critical for visibility -- on D9 mostly -- happy to downgrade again :-)
Comment #73
joegraduateThis line is causing a cspell failure (see https://www.drupal.org/pift-ci-job/2509141):
Comment #74
anchal_gupta commentedI have fixed CS error. Please review it
And address #73
Comment #75
liam morlandComment #76
robcarrPatch #74 applies to 9.4.8 with PHP8.1 - Deprecation errors do not appear
+1 RTBC
Comment #77
ameymudras commentedTested on Drupal 10.1.x and php 8.1
- The issue description is clear
- The patch applies cleanly and fixes the issue
- Patch addresses issues mentioned above
- No issues identified with the code
Marking this as RTBC
Comment #78
longwaveDeprecations use lowercase "drupal", this should be "drupal:10.1.0" and "drupal:11.0.0". Also, these deprecations need tests.
Comment #79
catchI think we should consider backporting this to 9.5.x (for removal in Drupal 11) even though it's technically too late, since the end result is it reduces the errors people see (on PHP 8.1 and higher) rather than just adding a new deprecation. That way modules can deal with the deprecation without bothering site owners. Discussed briefly with @longwave and slack and he agreed, so marking needs work for that.
Also some review issues:
This is escaping an empty string for no reason, I think it should be = $value ? static::placeholderEscape($value) : ''; or similar.
Message looks fine, let's just update to 9.5.x. Could also use a deprecation test.
Same thing here - let's not escape an empty string.
Comment #80
joegraduateUpdated patch from #74 with suggestions from #78 and #79.
Comment #81
liam morlandI suggest
isset()instead of!empty($value)otherwise it will not give the correct behavior if the value is zero.Comment #82
rivimeyAgree, isset() or is_null() should be used. empty(x) is not sufficient.
The new update has changed Drupal->drupal once but not twice as needed (this is why I don't like lines >100 chars long).
What's the logic of lower-case drupal here anyway? Drupal is a proper name => has an initial capital.
Comment #83
joegraduateAddressed comments from #81 and #82 as well as a missing use statement and some coding standards.
Comment #86
joegraduateTest fixes.
Comment #87
joegraduateFixed interdiff.
Comment #88
kim.pepperCan we
return ''early here?Can we
return ''early here instead of the $text check below?Comment #89
rivimeyKim, re:
(1) in escapeCdataElement, currently $text isn't being modified at all. It would make sense it would be, especially as there is a trigger_error, but I don't actually know that NULL input is banned in html_entity_decode().
(2) in #88 that seems sensible, indeed.
Comment #90
joegraduateAddressed suggestions from #88 and fixed the failing Html utility tests. Not really sure if there is a way to test the deprecation triggered within FormattableMarkup::placeholderEscape() since the changes to FormattableMarkup::placeholderFormat() now prevent NULL values from being passed to FormattableMarkup::placeholderEscape(). Maybe the deprecation trigger warning trigger_error() should be moved to FormattableMarkup::placeholderFormat() or the contsructor method instead?
Comment #91
kim.pepperThe link in the deprecation message needs to point to a change record. I have created a new draft one here https://www.drupal.org/node/3318826 that you can link to.
I think this change isn't needed now as placeholderEscape always returns a string now.
You can remove the test for it too.
Comment #92
joegraduateIncorporated suggestions from #91.
Should we remove the isset() checks added to calls to Html::escape() and Html::decodeEntities() as well now that those also always return strings?
Comment #93
rivimey@joegraduate, we still need the isset() calls in the code path leading to html::escape(), because the problems exist on *input* to escape et al, not the function's return value.
Doing the right thing on input is something that will become critical in D11 when the deprecation code is removed and (possibly) the function arg type is changed to 'string $text' rather than just '$text' or '?string $text'. Even now, when the deprecation code is hiding the problem, you get php errors in logs.
Comment #94
joegraduateThanks @rivimey. Does that mean we need to revert the change suggested in #91?
Comment #95
rivimeyIn #91 we have the line:
What this line says is:
In doing this we avoid passing the value NULL into placeholderEscape(), as required by the updated code.
Put simply, the change highlighted in #91 is good and it is needed.
Comment #96
kristen polTagging for bugsmash
Comment #97
gambryI reviewed patch and it looks good. Two things:
Comment #98
rivimeygambry, the message was changed to 'trigger a php error' because in D11 the intention is to remove the trigegr_error()s and tighten up the type definitions such that php will complain about type failure. Consequently there won't be any 'throw()' or similar; it will just be 'plain' code.
Yes, definitely the CR should match... I didn't know it was a thing to create specific issue for removing wrappers. Should such an issue be created *before* the code to be removed is even in Drupal?
Comment #99
gambryHey @rivimey. Yep, I was referring to the drupal versions mismatch.
Well, I thought that was the practice. But apparently I dreamed about it since is not on Drupal deprecation policy.
I've updated the CR to reflect the deprecation message: "[...] This behaviour is deprecated in Drupal 9.5.0 and will trigger a PHP error from Drupal 11.0.0."
Thanks everyone.
Comment #100
catchThis is resulting in a phpstan failure on 10.1.x:
Probably needs to be an explicit is_null() if the check is needed.
Comment #101
longwaveSo PHPStan is right. The lines in question are:
UrlHelper::stripDangerousProtocols()is documented as taking and returning a string; it also can't handle NULL:I wonder if we should just always cast a NULL $value to the empty string for all cases in
::placeholderFormat()? It's the only thing that makes any real sense to me; as we are dealing with array values, we can't enforce types in the method signature.The latest patch also doesn't have tests for the changes to
::placeholderFormat()or the deprecation in::placeholderEscape(). Ideally I think we want to test NULL values for all the possible placeholder types?Comment #102
longwaveImplemented #101; NULL values in the arguments are always cast to empty string, and added tests for each placeholder type. I think
::placeholderEscape()no longer needs a deprecation; it's protected so can only be called by the same class or subclasses, and we've fixed known callers here.Comment #103
alexpottFor core where this happened when were updating to support PHP 8.1 and 8.2 I pushed back against this type of fix because it always traced back to a message where actually doing an empty string replacement made no sense. If we hide errors here we're not listening to the system telling us our assumptions are wrong.
At the very least, I think this should trigger a deprecation too.
Comment #104
berdirYes, when I had one of these in contrib modules it was usually a hidden bug, sometimes only in tests due to missing config or so. Tracking them down can however be very tricky, due to our delayed rendering and generation of translated strings.
So, +1 on a deprecation and later (D11?) possibly an exception, but both should contain the string with the placeholders and the specific placeholder causing the problem IMHO, that would make it a lot easier to find where they are coming from.
Comment #105
alexpott#104 is a great idea! Making it easier to track this down could/will save people a lot of time.
Comment #106
longwaveNW for #103/104
Comment #107
rivimeyHere's a patch that replaces longwave's changes to FormattableMarkup.php following the suggestions made after that, but retains the additional test in FormattableMarkupTest.php.
I have also taken the chance to improve the function docs for placeholderFormat().
Comment #108
rivimeyComment #109
rivimeyOops, wrong patch root.
Comment #110
rivimeyFix style complaints
Comment #112
rivimeyThe test failure is from the code @longwave added and I'm not sure what the correct resolution is.
Comment #113
ameymudras commentedI don't think the test case for
['<em class="placeholder"></em>', '%empty', ['%empty' => NULL]],is required. I've removed it to fix the issueComment #115
longwaveMost of the docs changes appear to be out of scope - let's try and keep this patch focused on solving the issue at hand, docs improvements can be done separately.
I added the test case as we need to know what should happen in the case NULL is passed and a
%placeholder is used. Unsure if it should return an empty string entirely, or an empty<em>tag?Comment #116
liam morlandI don't think it ever makes semantic sense to have an empty
emelement.Emphasized emptiness sounds like the sound of one hand clapping.
Comment #117
longwaveThat is what passing NULL or the empty string currently return:
This would be a behaviour change - and do we change the empty string at the same time for consistency?
Comment #118
liam morlandThat change should probably be a separate issue so that this one can focus on the type declarations.
Comment #119
rivimeyLets focus on making the code behave well without changing its meaning. If people feel there is a bug to be squashed with e.g. empty tags then by all means create an issue to fix it. This issue has already feature-creeped itself into the next version of Drupal!
Comment #120
douggreen commentedThis hasn't addressed htmlspecialchars_decode(), which has a similar problem since PHP 8.1, mainly because Html does not have a wrapper for htmlspecialchars_decode(). Can we add a wrapper and solve it in whatever manner is decided for other methods.
There are several issues that would have been solved in a single place if we had this wrapper
* #3301782: PHP8 Deprecated function : htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated
* #3298778: PHP 8.1 Deprecated function: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated
* #3324460: Deprecated function: htmlspecialchars() with PHP 8.1 when viewing schedules
Comment #121
alexpottPatch attached fixes #113 to not change the output of %placeholder when the value is NULL. It tests the deprecations for all placeholders. And removes unnecessary change. For example, it removes the stricter typehinting on Html::escape() - it's out-of-scope and also would be a behaviour change - see https://3v4l.org/2fkmR
The patch attached works on 9.5.x and 10.1.x :)
Comment #122
alexpottRemoving more unnecessary change.
Comment #123
longwaveProbably should say "drupal:11.0.0" to match other version references, and also end with a full stop.
Otherwise this looks good and would be great to get into 9.5.0.
Comment #124
alexpottI've rewritten the summary to detail the latest approach as based on #104
Comment #125
alexpott@longwave good point. Fixed and pointed to CR.
Comment #126
longwaveThanks, even better. Everything looks good, this should help track down the root cause of multiple different issues.
Comment #127
alexpottSlight improvement on one of the comments.
Comment #129
catchThis looks good now.
I think there's a question whether we want to throw an exception or move to an unsilenced E_USER_WARNING or similar for 11.x, but we can decide that when we get there.
This is technically a new deprecation in 9.5.x, but it's replacing an unsilenced one with a silenced one, unless you're still on PHP 7.4, but it's still silenced on PHP 7.4 too.
Committed/cherry-picked/pushed to 10.1.x, 10.0.x, and 9.5.x, thanks!
Comment #130
rivimey@alexpott, @longwave @catch Given that some of the changes were removed (a good thing), have issues been raised to remind us that they were considered a problem? Even a bullet-point summary here of what was dropped would be helpful.
Comment #132
liam morlandThe owner of merge request !1657 will need to close it.
Comment #134
ghost of drupal pastAn empty string field value is NULL, if that makes its way to Html::escape , that will trigger this notice. For example t('@foo', ['@foo' => $node->foo->value]) goes to TranslatableMarkup::placeholderFormat() and then FormattableMarkup::placeholderEscape and then straight to Html::escape($value). NestedArray::getValue() will also return a NULL on key not found and that's not necessarily a bug either. parse_url does "If the requested component doesn't exist within the given URL, null will be returned". And so on.
While it's possible to patch the code chain lined up above, there are any number of ways where a completely valid NULL can make its way to Html::escape(). It is a complete waste of time to hunt down every single one. This should be rolled back and a silent string cast added. (It was a bad idea for PHP as well, they are hell bent lately on adding a lot of completely needless busywork to upgrade, we do not need to copy theirs, rather we should make the life of developers easier.)
In general, this issue attacked the problem from the wrong end. If we want to steer Drupal into a strict typed land then we need to take a look at our data producers first and only then change the consumers.
Comment #135
john.oltman commentedA custom entity type without a label will trigger the error mentioned by @ghost-of-drupal-past when using a DraggableListBuilder and when saving the entity using EntityForm. I'll open a separate issue, but the solution might be a rollback of this change.