AdvancedCustomFields / AdvancedCustomFields/acf

Drop trap, acf_after_title

Open Beginner friendly
#1,029 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
945
Forks
197
PR merge metrics
No merged PRs in 30d

Description

Describe the bug
ACF renders a hidden, empty #acf_after_title-sortables meta box container on every block editor post screen, even when no field group uses the acf_after_title position. Because WordPress' postboxes.js connects all .meta-box-sortables elements as jQuery UI sortable drop targets, users can drag non ACF meta boxes into this invisible container. The drop is persisted by postboxes.save_order() into the user's meta-box-order_{$screen} user meta under an acf_after_title bucket.

On the next load, WP core re-registers those box IDs into the acf_after_title context via add_meta_box( $id, null, null, $screen, $box_context, 'sorted' ) (wp-admin/includes/template.php:1324–1332). Gutenberg only renders side/normal/advanced visibly, so the box disappears for that user, the corruption is per-user, not site wide, and is permanent because ACF's existing self repair never runs in this scenario.

To Reproduce

  1. Install ACF 6.8.9 with no field group set to the "High (after title)" position.
  2. Open any post in the block editor with at least one classic meta box present (e.g. a plugin meta box).
  3. Inspect the hidden .metabox-base-form form rendered by the_block_editor_meta_boxes(), it contains an empty <div id="acf_after_title-sortables" class="meta-box-sortables"></div> output by ACF_Form_Post::edit_form_after_title()do_meta_boxes( get_current_screen(), 'acf_after_title', $post ) (includes/forms/form-post.php:206).
  4. Start dragging a meta box in the editor. assets/build/css/acf-input.css (body.is-dragging-metaboxes #acf_after_title-sortables { outline: 3px dashed; min-height: 60px; }) paints the invisible container as a visible drop target (assets/src/sass/_postbox.scss:63).
  5. Drop the box into the acf_after_title drop zone.
  6. Reload the editor. The dropped box no longer appears anywhere on the screen, and get_user_option( 'meta-box-order_{$screen}' ) now contains an acf_after_title bucket with the box ID.

Expected behavior
With no field groups registered at the acf_after_title position, the hidden form should contain no #acf_after_title-sortables container, so there is no droppable target and no way to corrupt the user's meta box order. Field groups actually positioned acf_after_title must continue to render, sort, and save as before, and the hidden acf_form_data() inputs (nonce/screen/post_id) must still render on every post edit screen.

Screenshots or Video
N/A

Code
No field group or block code is involved, the bug reproduces with zero ACF field groups at the acf_after_title position and any other plugin registered meta box.

Version Information:

  • WordPress Version 6.9.x and later
  • PHP Version 8.2
  • ACF Version 6.8.9
  • Browser Chrome, Safari, Firefox

Additional context
Why the existing repair never fires, WP core's the_block_editor_meta_boxes() (wp-admin/includes/post.php):

  1. Applies filter_block_editor_meta_boxes (~line 2375), at this point the acf_after_title bucket only contains boxes registered at that position (i.e. ACF field groups with position acf_after_title). With none present, ACF_Form_Gutenberg::filter_block_editor_meta_boxes() never attaches its modify_user_option_meta_box_order repair filter (includes/forms/form-gutenberg.php:107–149).
  2. ACF's hidden-fields render (block_editor_meta_box_hidden_fieldsACF_Form_Post::edit_form_after_title()) is where the first do_meta_boxes() call happens core re-registers box IDs found under acf_after_title in the user's saved order.
  3. Only side/normal/advanced render visibly afterwards, then the box is gone.

Root causes:

  • includes/forms/form-post.php, ACF_Form_Post::add_meta_boxes() unconditionally adds add_action( 'edit_form_after_title', ... ) (~line 171), and edit_form_after_title() calls do_meta_boxes( ..., 'acf_after_title', ... ) with no guard for whether anything exists in that context. do_meta_boxes() always outputs the <div id="{context}-sortables" class="meta-box-sortables"> wrapper, even when empty.
  • includes/forms/form-gutenberg.php, block_editor_meta_box_hidden_fields() re-runs the same unguarded render inside the hidden form.

Suggested fix (render gating): in ACF_Form_Post::edit_form_after_title(), guard the do_meta_boxes( ..., 'acf_after_title', ... ) call on isset( $wp_meta_boxes[ get_current_screen()->id ]['acf_after_title'] ), keeping acf_form_data() unconditional. This removes the empty drop target while preserving rendering when the context genuinely has content, and works for both the classic and block editors since both paths call the same method.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in includes/forms/form-post.php, reading ACF_Form_Post::add_meta_boxes() and edit_form_after_title(), then compare the hidden-form path in includes/forms/form-gutenberg.php. Verify that acf_form_data() remains unconditional, that the acf_after_title container is omitted when its context is empty, and that field groups using that position still render and sort.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.