{"id":19036002,"date":"2026-10-04T05:07:40","date_gmt":"2026-10-04T05:07:40","guid":{"rendered":"https:\/\/wordpress.org\/support\/topic\/bug-undefined-array-key\/"},"modified":"2026-10-04T05:07:40","modified_gmt":"2026-10-04T05:07:40","slug":"bug-undefined-array-key","status":"publish","type":"topic","link":"https:\/\/wordpress.org\/support\/topic\/bug-undefined-array-key\/","title":{"rendered":"Bug: Undefined array key"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Bug: <code>Undefined array key<\/code> in <code>Media_Item_Query::attachment_urls_to_ids()<\/code> with case-insensitive <code>_wp_attached_file<\/code> collisionsEnvironment<\/p>\n\n\n\n<ul>\n<li>Smush: 4.3.4<\/li>\n\n\n\n<li>WordPress: 7.1.2<\/li>\n\n\n\n<li>WooCommerce: 11.1.2<\/li>\n\n\n\n<li>PHP: 8.4<\/li>\n\n\n\n<li>Database <code>wp_postmeta.meta_value<\/code> collation: <code>utf8mb4_unicode_ci<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Problem<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>Smush\\Core\\Media\\Media_Item_Query::attachment_urls_to_ids()<\/code> can produce PHP <code>Undefined array key<\/code> warnings when two WordPress attachments have <code>_wp_attached_file<\/code> values that differ only by letter case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, assume the database contains two valid attachment records:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/Picture123.jpg\n2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both attachments may be valid, with separate attachment IDs, metadata and physical files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Smush attempts to resolve:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#047;&#047;example.com\/wp-content\/uploads\/2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>attachment_urls_to_ids()<\/code> creates a PHP lookup array using the relative URL as a key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$relative_key_absolute_value&#091; $relative_url ] = $absolute_url;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore the array contains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">but not:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/Picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Later, Smush queries <code>wp_postmeta<\/code> using:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$sql = \"SELECT post_id, meta_value\n        FROM $wpdb-&gt;postmeta\n        WHERE meta_key = '_wp_attached_file'\n        AND meta_value IN ({$in})\";<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On a standard case-insensitive WordPress database collation such as <code>utf8mb4_unicode_ci<\/code>, the comparison is case-insensitive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consequently, a query for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">can return both records:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/Picture123.jpg\n2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Smush then assumes every <code>meta_value<\/code> returned by SQL exists as an exact PHP array key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>foreach ( $results as $result ) {\n    $meta_value            = $result&#091;'meta_value'];\n    $original_absolute_url = $relative_key_absolute_value&#091; $meta_value ];\n\n    $ids&#091; $original_absolute_url ] = $result&#091;'post_id'];\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">PHP array keys are case-sensitive, unlike the SQL comparison above.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore, when <code>$meta_value<\/code> is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/Picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">but the array contains only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">PHP generates:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PHP Warning: Undefined array key \"2024\/11\/Picture123.jpg\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reproduction<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create two image attachments whose <code>_wp_attached_file<\/code> values differ only by case:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024\/11\/Picture123.jpg\n2024\/11\/picture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify that the database column uses a case-insensitive collation such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>utf8mb4_unicode_ci<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then execute the equivalent lookup:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT post_id, meta_value\nFROM wp_postmeta\nWHERE meta_key = '_wp_attached_file'\nAND meta_value IN ('2024\/11\/picture123.jpg');<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both attachment rows can be returned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The same behavior can be demonstrated through WordPress <code>$wpdb<\/code>: the returned <code>meta_value<\/code> may not be byte-for-byte identical to the string supplied in the <code>IN()<\/code> clause.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When this happens during <code>Media_Item_Query::attachment_urls_to_ids()<\/code>, the subsequent PHP array lookup generates the warning.Expected behavior<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>attachment_urls_to_ids()<\/code> should not assume that every <code>meta_value<\/code> returned by a case-insensitive SQL comparison is an exact key in <code>$relative_key_absolute_value<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Attachment URL resolution should preserve exact filename\/path matching, including case.Actual behavior<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A case-insensitive SQL match can return additional attachment rows whose <code>_wp_attached_file<\/code> differs only by case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Those values are subsequently used as case-sensitive PHP array keys without checking that the key exists, resulting in <code>Undefined array key<\/code> warnings and potentially ambiguous attachment URL-to-ID resolution.Scope<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This does not require corrupt WordPress attachment metadata or missing files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The issue is reproducible with two otherwise valid attachments whose filenames differ only by case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is also not specific to non-ASCII filenames. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Picture123.jpg\npicture123.jpg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">is sufficient to reproduce the underlying SQL\/PHP comparison mismatch.Possible fix<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The SQL lookup should ideally use exact\/binary matching so that its matching semantics agree with the PHP lookup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alternatively, at minimum, the result should be validated before accessing the lookup array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$meta_value = $result&#091;'meta_value'];\n\nif ( ! isset( $relative_key_absolute_value&#091; $meta_value ] ) ) {\n    continue;\n}\n\n$original_absolute_url = $relative_key_absolute_value&#091; $meta_value ];<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">However, simply suppressing the warning would not completely address the underlying ambiguity. An exact\/case-sensitive attachment-path lookup would appear to be the more robust solution.Additional note<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This code path can be reached during normal frontend page processing through <code>Attachment_Url_Cache_Controller<\/code>, which collects image URLs from page elements and calls:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$this-&gt;media_item_query-&gt;attachment_urls_to_ids( $this-&gt;bulk_image_urls );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore the warning can occur during ordinary frontend requests without manually running Bulk Smush or another media optimization operation.<\/p>\n","protected":false},"template":"","class_list":["post-19036002","topic","type-topic","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19036002","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic"}],"about":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19036002\/revisions"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/media?parent=19036002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}