Skip to content

Fix fatal error when passing a float column width to rtrim() - #2725

Open
westonruter wants to merge 4 commits into
trunkfrom
fix/auto-sizes-columns-percentage-width
Open

westonruter wants to merge 4 commits into
trunkfrom
fix/auto-sizes-columns-percentage-width

Conversation

@westonruter

@westonruter westonruter commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes #2724

Use of AI Tools

None initially, but then review and additional commits provided by Claude Opus 5.5.

@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: westonruter <westonruter@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@westonruter westonruter added this to the auto-sizes n.e.x.t milestone Oct 16, 2026
@github-actions github-actions Bot added the [Plugin] Enhanced Responsive Images Formerly "Auto Sizes" [slug: auto-sizes] label Oct 16, 2026
@westonruter westonruter added [Type] Bug An existing feature is broken and removed [Plugin] Enhanced Responsive Images Formerly "Auto Sizes" [slug: auto-sizes] labels Oct 16, 2026
@westonruter

westonruter commented Oct 16, 2026 •

Copy link
Copy Markdown
Member Author

🤖 Comment by Claude Opus 5.5

Origin of the bug

There are two parts: Gutenberg changed the attribute's type, and the plugin later made that change fatal.

1. Gutenberg changed the Column width attribute from number to string in 1cad0e1 (WordPress/gutenberg#24711, "Use UnitControl instead of RangeControl for column width"). It was merged on 2020-09-29 and first shipped in Gutenberg 9.2.0, which landed in WordPress 5.6.

  • In block.json, width went from {"type":"number","min":0,"max":100} to {"type":"string"}.
  • save went from flexBasis: width + '%' to flexBasis: width, so the unit is now part of the value.
  • A deprecation was added in column/deprecated.js. Its isEligible( { width } ) { return isFinite( width ); } and migrate() convert 33.33 into "33.33%", which is the conversion seen when toggling the editor's visual mode.
  • The original numeric width attribute came from 5494bc5 (Block Library: Add width attribute for resizable Column blocks gutenberg#15499, Gutenberg 5.7, May 2019). Any Column saved between Gutenberg 5.7 and 9.2 (roughly WordPress 5.3–5.5) therefore stores a bare number.

Block deprecations only run in the editor. Server-side render filters receive the raw stored attributes, so $block['attrs']['width'] is a float or int for any such post that has not been re-saved since.

2. On the plugin side, the rtrim() line was introduced in 54ee498 ("Calculate column width per parent columns") as part of #1795, released in auto-sizes 1.5.0. At that point the bug was latent: without strict types, rtrim( 33.33, '%' ) silently coerced the float to "33.33" and worked. It became a fatal error with #2424, which added declare( strict_types = 1 ) and shipped in auto-sizes 1.8.0.

The string cast in this PR addresses the cause and not just the symptom. The legacy numeric format always meant a percentage from 0 to 100, so (string) 33.33 → "33.33" → 0.3333 is the correct value. Integer values like {"width":50} work as well.

Other faulty assumptions in improve-calculate-sizes.php

Same kind of risk (strict types combined with raw attributes or context):

  • Lines 116 and 144: $block->context['postId'] is passed to auto_sizes_get_featured_image_attachment_id( int $post_id ). Core always supplies an int (render_block(), Post Template, the block renderer REST endpoint). However, a third-party block can expose postId from a raw attribute through providesContext, and a numeric string there would now cause a TypeError. An (int) cast would be a cheap safeguard. The risk is low.
  • Line 106: $block->attributes['align'] ?? '' is passed uncast into string $align. Core always stores align as a string, so the risk is very low.

Wrong assumptions about units (not fatal, but the computed sizes are wrong):

Note

Since these and the issue below are not fatal errors, they are addressed separately in #2726.

  • Line 370, Column width: the value is assumed to be a percentage. Since Use UnitControl instead of RangeControl for column width gutenberg#24711, the Column width control offers %, px, em, rem and vw. With "width":"300px", floatval( rtrim( '300px', '%' ) ) / 100 yields 3.0, so the column is treated as 300% of its container. In the wide case nothing caps this, so the layout width is tripled. "20em" yields 0.2. The percentage parsing should only apply when the value ends in %, otherwise falling through to the column_count branch.
  • Line 107, core/post-featured-image width: (int) $block->attributes['width'] is fine for core/image, which only allows px. Its width became a string like "300px" in Image block: Fix stretched images constrained by max-width gutenberg#53274, and (int) handles both the legacy number and the string. The Post Featured Image block, however, allows px, %, vw, em and rem, so "50%" is interpreted as a 50px resize width.

Unrelated to types, but noticed in passing: the condition ( $x > 0.0 || $x < 1.0 ) at lines 232–233, 258–259 and 382 is always true. It was most likely intended to be &&.

westonruter and others added 2 commits October 15, 2026 22:27
Block context is not type-coerced, and a third-party block can provide
`postId` from a raw attribute via `providesContext`. With strict types,
a numeric string there would cause a TypeError when passed to
`auto_sizes_get_featured_image_attachment_id()`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Block attributes are not type-coerced on the server, so `align` is passed
through exactly as stored in the block comment delimiter. With strict
types, a non-string value would cause a TypeError when passed to the
`string $align` parameter of `auto_sizes_calculate_better_sizes()`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.50%. Comparing base (6c5c96d) to head (9784590).

Additional details and impacted files
@@           Coverage Diff           @@
##            trunk    #2725   +/-   ##
=======================================
  Coverage   70.50%   70.50%           
=======================================
  Files          91       91           
  Lines        7869     7869           
=======================================
  Hits         5548     5548           
  Misses       2321     2321           
Flag Coverage Δ
multisite 70.50% <100.00%> (ø)
single 35.34% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added the [Plugin] Enhanced Responsive Images Formerly "Auto Sizes" [slug: auto-sizes] label Oct 16, 2026
The raw `align` attribute of a container block is copied into the
`max_alignment` context, which is later passed to the `string
$max_alignment` parameter of `auto_sizes_calculate_better_sizes()`. Block
attributes are not type-coerced on the server, so with strict types a
non-string value would cause a TypeError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Enhanced Responsive Images Formerly "Auto Sizes" [slug: auto-sizes] [Type] Bug An existing feature is broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fatal error in Enhanced Responsive Images when using old Columns block with a percentage float width

1 participant