Skip to content

Editor page canvas stuck on spinner in local dev: section iframes never render #1235

Open

Description

@elemdos

Summary

Opening a page in the editor under primo dev locally leaves the main canvas on a permanent loading spinner. Section wrappers are created in the DOM but each one is empty — ComponentNode never renders its <iframe>, so the page never reports itself mounted.

Reproduced on unmodified main (fd175fa / 6558bca). Not caused by any in-flight branch — I hit this while verifying #1233 and checked out pristine main to confirm.

Reproduce

  1. cd primo-sites && primo dev (a workspace with a multi-section page — used coffee-shop, pages/about.yaml, 5 sections)
  2. Open http://coffee-shop.localhost:3000/admin/site/about
  3. Canvas spins indefinitely

Observed

// after 8s on /admin/site/about
{ sectionNodes: 5, iframes: 0, spinnerVisible: true, allWrappersEmpty: true }

All 5 [data-section] wrappers are present, each children.length === 0 and 32px tall. No console errors (only an unrelated __primo_dev_ws__ websocket warning). Data loads fine — every page_sections / site_symbols / page_section_entries request returns 200, and the records exist when queried with an auth token.

Why it hangs

The spinner is gated on a mount counter in src/lib/builder/views/editor/Page.svelte:

{#if !page_mounted && sections && sections.length > 1}

page_mounted only becomes true once sections_mounted >= sections.length. Each increment comes from on:mount={() => sections_mounted++} on ComponentNode, dispatched by dispatch_mount().

But every dispatch_mount() path depends on the iframe existing — onload={setup_component_iframe}, the MutationObserver, the component-error message handler — and the iframe itself is gated at ComponentNode.svelte:1262:

{#if $site_html && generated_js}
  <iframe ... onload={setup_component_iframe}></iframe>
{/if}

So when that condition stays false, no iframe → no mount → counter never reaches target → spinner forever. $site_html does get populated (the page <head> has 80 children), which points at generated_js never being produced — i.e. the per-block processCode compile in ComponentNode isn't completing or isn't assigning.

The actual bug

Independent of why the compile doesn't finish, the failure mode is wrong: a block that never compiles produces no iframe, no error branch, and no mount signal, so the whole canvas is held hostage by one silent block. There's an {#if error} branch, but the paths that set error also require the iframe to exist, so a pre-iframe compile failure can't reach it.

Worth fixing in two parts:

  1. Root cause — why generated_js is never set for these blocks in local dev.
  2. Resilience — the mount counter shouldn't be able to deadlock. A block that fails to compile should surface its error and still count as "settled", so one bad block degrades to a visible error instead of an indefinite spinner with no diagnostics.

Impact

The editor's primary view is unusable locally — you can still navigate sidebars, page types, modals and block code, but not the page canvas. Verification of #1233 had to route around it.

Environment

  • main @ 6558bca (also repros at fd175fa)
  • CLI 0.1.24, primo dev (both --author files and --author cms)
  • macOS, Chromium

Activity

  1. elemdos commented on Sep 18, 2026

    @elemdos
    CollaboratorAuthor

    Opened #1236 with the resilience half of this: the canvas now reveals once mounting stalls and logs how many sections never reported, instead of spinning indefinitely.

    That does not fix the root cause — content data still stops resolving for these sections in local dev, so they render no iframe. Leaving this open for that.

    One extra data point from diagnosing: every dependency resolves fine at the API level for the stuck sections (symbol found, 3 fields, 3 entries, uploads present), so the stall appears to be in the client-side reactive resolution in useContent, not in the data itself.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions