Skip to content

Fix cached unblaze blocks after state flush - #207

Merged
ganyicz merged 6 commits into
livewire:mainfrom
matt-h:unblaze-fix
Aug 24, 2026
Merged

Fix cached unblaze blocks after state flush#207
ganyicz merged 6 commits into
livewire:mainfrom
matt-h:unblaze-fix

Conversation

@matt-h

@matt-h matt-h commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes cached @unblaze components throwing an undefined array key after flush clears static state. I ran into this when rendering Flux inputs, which use @unblaze for validation state.

Previously, compiled components retained the token while its replacement content existed only in memory:

Undefined array key "QgnFk95bfK"
Livewire\Blaze\Unblaze::{closure:Livewire\Blaze\Unblaze::replaceUnblazePrecompiledDirectives():75} in /srv/www/vendor/livewire/blaze/src/Unblaze.php:87
preg_replace_callback in /srv/www/vendor/livewire/blaze/src/Unblaze.php:75
Livewire\Blaze\Unblaze::replaceUnblazePrecompiledDirectives in /srv/www/vendor/livewire/blaze/src/BladeRenderer.php:142

The replacement content is now embedded in the compiled component and restored whenever it runs.

I'm not sure if this is the best way to go about fixing this, but it works for me.

Testing

Added a regression test that renders a cached @unblaze component, flushes its state, and renders it again.

Persist unblaze replacement content in compiled components so cached components can restore their replacements after Octane clears static state.

Add a regression test covering cached component rendering across state flushes.
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Benchmark Result: Default

Attempt Blade Blaze Change
#1 355.69ms 14.67ms 95.9%
#2 354.57ms 14.35ms 96%
#3 357.46ms 14.53ms 95.9%
#4 359.23ms 14.44ms 96%
#5 357.93ms 14.48ms 96%
#6 357.85ms 14.39ms 96%
#7 356.38ms 14.77ms 95.9%
#8 354.40ms 14.29ms 96%
#9 353.89ms 14.75ms 95.8%
#10 358.22ms 14.50ms 96%
Snapshot 354.68ms 14.61ms 95.9%
Result 356.92ms (~) 14.49ms (~) 95.9% (~)

Median of 10 attempts, 5000 iterations x 10 rounds, 46.68s total

To run a specific benchmark, comment /benchmark <name>
attributes, aware, class, default, forwarding, merge, named-slots, no-attributes, slot, compilation

@ganyicz

ganyicz commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Hi @matt-h

Thanks for reporting!

Would you mind explaining exactly when do you hit this? Sounds like an Octane issue?

@matt-h

matt-h commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

@ganyicz I'm not using octane, just normal fpm/nginx.

It seems to happen most times when a page with a flux input is loaded right after a fresh deploy of the app. It only seems to be the first load and then it works fine.

php artisan optimize is run during the deploy process.

The error doesn't actually seem to break the page at all when it is loaded, the error just gets reported to the logs.

@matt-h

matt-h commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

It seems to be related to the fresh view:cache

When working through the problem with my agent it gives this explanation.

Without view:cache, the first request compiles the consuming page:

  • Blaze sees the Flux component.
  • It compiles the Flux component and populates $unblazeReplacements.
  • It immediately consumes that replacement while compiling the page.
  • Laravel saves the fully compiled page.
  • Later requests execute that finished page and don’t consult $unblazeReplacements again.

With view:cache, the deployment process can create the Blaze component cache without producing every final runtime variant of the consuming page. In particular, Livewire pages and dynamically resolved Flux components may still undergo folding when first requested.

That first web request then does this:

  • The consuming page still needs compilation/folding.
  • Blaze finds the component already cached by the deployment process.
  • It therefore skips processUnblazeDirectives(), which is what populates $unblazeReplacements.
  • It encounters the cached random token and indexes an empty array.
  • The resulting consuming page is nevertheless compiled and cached.

Subsequent requests execute that final compiled page, so they no longer enter the failing Blaze compilation path. Thus it appears as a first-request-after-deploy warning rather than an error on every request.

@ganyicz

ganyicz commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Thanks!

@ganyicz
ganyicz merged commit b1594ab into livewire:main Aug 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants