[BUG - 4.0.0] Pro Forms field hydration regression with nested {brf_post_meta:...} (Data overwrite risk)

Hi Daniele,

Hope you’re doing great! First off, congrats on getting Bricksforge 4.0.0 out the door—huge milestone.

We just updated one of our projects to 4.0.0 and caught a regression in how Pro Forms hydrates field values when brf_post_meta uses a nested dynamic tag for the post ID. To save you time digging around, our team already ran an isolation matrix to pinpoint exactly where the parser is tripping up.

1. Our Environment

  • Bricksforge: 4.0.0 (regression appeared right after updating from 3.x)
  • Bricks: 2.4.1 | WP: 7.1.2 | PHP: 8.3.33
  • Server: Apache 2.4.68 (Debian) | DB: MariaDB 11.8.9
  • Fields: Meta Box AIO 3.12.0 (standard wp_postmeta storage, verified directly in DB)

2. What’s Happening

In our “edit” forms, we pre-populate fields using brf_post_meta with the post ID coming dynamically from a URL parameter:

{brf_post_meta:META_KEY:{url_parameter:post_id}}

In 3.x, the forms opened with all saved values pre-filled. In 4.0.0, this exact syntax resolves to an empty string inside Pro Forms fields, affecting:

  • Text / Number field → Value
  • Select → Option → Conditionally Selected → Selected If Value
  • Checkbox → Conditionally Checked → Checked If Value

(Important: If a user submits the form in this state, the empty/default values overwrite the existing postmeta in the database, causing silent data loss—like resetting statuses or unchecking active flags).

3. Isolation Matrix

We tested all variations on the exact same page request (...?post_id=45, same user, verified in wp_postmeta that post 45 holds escola_sigla_escola = "C M TIRADENTES"):

# Where the tag is placed Tag Result
A Bricks Basic Text (outside form) {url_parameter:post_id} :white_check_mark: 45
B Bricks Basic Text (outside form) {brf_post_title:{url_parameter:post_id}} :white_check_mark: Correct title
C Bricks Basic Text (outside form) {brf_post_meta:escola_sigla_escola:45} :white_check_mark: Correct value
D Bricks Basic Text (outside form) {brf_post_meta:escola_sigla_escola:{url_parameter:post_id}} :white_check_mark: Correct value
E Pro Forms Text field → Value {brf_post_title:{url_parameter:post_id}} :white_check_mark: Correct title
F Pro Forms Text field → Value {brf_post_meta:escola_sigla_escola:45} (Literal ID) :white_check_mark: Correct value
G Pro Forms Text field → Value {brf_post_meta:escola_sigla_escola:{url_parameter:post_id}} :cross_mark: EMPTY
H Pro Forms Option / Checkbox Conditional {brf_post_meta:KEY:{url_parameter:post_id}} :cross_mark: Never matches

As you can see:

  • {url_parameter:post_id} works inside the form when nested in a one-argument tag like brf_post_title (E).
  • brf_post_meta works inside the form with a literal ID (F).
  • The full nested tag works right outside the form on the same render (D).
  • It only fails inside Pro Forms field settings when brf_post_meta (two arguments) receives its post ID from a nested tag (G, H).

4. Our Hypothesis (Just a lead)

I saw in the 4.0.0 changelog that brf_post_* tags were updated to return empty (instead of falling back to the current post) when the passed post ID resolves to nothing.

Looking at the matrix, our hunch is that in the Pro Forms field-rendering pipeline, the nested {url_parameter:post_id} isn’t being evaluated before brf_post_meta splits its arguments by :. Since the nested tag itself has a colon, the post ID argument probably arrives malformed/empty, triggering the new 4.0.0 empty return. That would also explain why brf_post_title (E) still works, since it doesn’t split a second argument.

5. Quick Steps to Reproduce

  1. Create a post (e.g., ID 123) with custom field brf_test_key = hello.
  2. On a page, add a Bricks Basic Text with {brf_post_meta:brf_test_key:{url_parameter:post_id}}.
  3. Add a Pro Forms element with two Text fields:
  • Field 1 Value: {brf_post_meta:brf_test_key:{url_parameter:post_id}}
  • Field 2 Value: {brf_post_meta:brf_test_key:123}
  1. Load the page with ?post_id=123.
  • Expected: Basic Text and both form fields output hello.
  • Actual (4.0.0): Basic Text and Field 2 output hello, while Field 1 is empty.

(Transparency note: In our production environment, these forms live inside a Bricks Popup template rendered on the page, and we haven’t yet stripped out all other plugins or tested outside the popup context. However, the workaround below confirms the form fields themselves are rendering dynamic data fine).

6. Current Workaround in Production

To keep production safe for now, we whitelisted a custom helper via bricks/code/echo_function_names ({echo:samar_popup_meta('META_KEY','POST_TYPE')}) that grabs $_GET['post_id'] directly. It works in all affected spots (Value, Selected If Value, and Checked If Value), confirming that Pro Forms fields evaluate dynamic tags properly in general—it’s really just the brf_post_meta + nested tag combo.

Let me know if you need any extra testing on our end!

Best regards,

Jayron Castro
CEO, Kstros.com

Hi Jayron,

thanks for the detailed report and the isolation matrix, that saved a lot of time. I checked the code and can confirm the bug. The trigger is Bricks 2.4 though, not the 4.0.0 update itself.

Up to Bricks 2.3.x, Bricks resolved the inner tag first, so our provider received the finished post ID. Since Bricks 2.4, the dynamic data parser keeps nested tags inside the outer tag and hands the whole thing to the provider unresolved. The arguments are then split at every colon, so for {brf_post_meta:KEY:{url_parameter:post_id}} our tag receives three arguments: KEY, “{url_parameter” and “post_id}”. The post ID argument is the literal text “{url_parameter”, which is not a number, so the value comes back empty. Bricks’ own tags that accept nested arguments resolve them inside their provider since 2.4, and our brf_ tags don’t do that yet. Debra reported the same for {brf_acf_field:…:{url_parameter:id}} and it went away after rolling back to Bricks 2.3.13, which matches.

The 4.0.0 change you found only decides what happens once the ID is empty: before, the tag fell back to the hosting post and prefilled the fields with the wrong post’s data, which was arguably worse for your overwrite scenario. It didn’t cause the empty argument.

Why the same tag still works for you in the Basic Text element and brf_post_title works inside the form, I can’t explain from the code yet. Both go through the same parser, so I’ll check that while fixing it.

The fix is on our side: the brf_ tags will resolve nested dynamic tags in their arguments themselves, so the syntax works again on Bricks 2.4. I’ll ship it in the next Bricksforge update. Until then your echo helper is the right workaround, and a literal post ID keeps working as you saw.

Best
Daniele

Hi Daniele,

That explanation makes perfect sense! We hadn’t considered the Bricks 2.4 core parser change, but the colon-splitting behavior you described perfectly explains why the argument arrived completely broken ({url_parameter vs post_id}).

Also, returning an empty string (your 4.0.0 change) instead of falling back to the current post was definitely a lifesaver for our data integrity!

We will keep our custom PHP echo helper in place for our production sites until the next Bricksforge update drops.

Thanks again for the fast turnaround, the transparency, and the deep dive into the parser. Have a great week!

Best regards,

Jayron Castro
CEO, Kstros.com