dotCMS / dotCMS/core

UVE: editor silently accepts legacy params-only CLIENT_READY, leaving migrated headless clients half-connected (no content events, no warning)

Open
#36,713 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : UVE Team : Scout Type : Defect UPL
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Problem

The UVE editor silently accepts the legacy, beta-era params-only CLIENT_READY shapeinitUVE({ params: { depth: 3 } }) — and leaves the headless client in a half-connected state:

  • The client is marked ready (setIsClientReady(true)), params are honored on the editor's page fetch (depth appears on the iframe URL)
  • Non-gated events (uve-request-bounds / uve-flush-bounds / uve-scroll-inside-iframe / selection) flow normally
  • But uve-set-page-data / uve-reload-page are never emitted on contentlet add/remove/save, so CONTENT_CHANGES / PAGE_RELOAD subscriptions never fire and the canvas never re-renders until a manual browser refresh

There is no warning, no error, and no documentation stating that registering a GraphQL query via CLIENT_READY is required for content-event delivery. The runtime accepts a shape the SDK types already reject (DotCMSPageResponse has no params field), and the degradation is completely silent.

Why this matters: every integration built on the 0.0.1-beta.x line that migrates to 26.7.x and keeps its hand-wired bridge (initUVE({params}) + manual createUVESubscription) will hit exactly this half-working state. Diagnosing it requires instrumenting the postMessage channel and reading editor source — this cost a real integration team days of instrumentation and a multi-day support investigation.

Code path (verified on main)
  • Gate: edit-ema-editor.component.ts$handleReloadContentEffectif (pageType === PageType.HEADLESS && !hasClientQuery) return; (deliberate: "Never push a REST-sourced pageAsset… skip until a GraphQL-backed update is available")
  • requestMetadata is only set from CLIENT_READY when devConfig.graphql.query is present: dot-uve-actions-handler.service.tsCLIENT_READY handler (setCustomClient only if (query))
  • params-only configs still get pageReload(pageParams) + setIsClientReady(true) → the half-connected state, with no feedback
  • uve-reload-page only fires on narrow paths (e.g. SAVE_PAGE with clientAction === EDIT_CONTENTLET), so add/remove emits nothing to these clients
  • SDK type contract (DotCMSPageResponse, sdk/types/.../public.ts) doesn't include params — the runtime accepts a shape the types reject
Repro
  1. Headless site in UVE; the app initializes with initUVE({ params: { depth: 3 } }) and subscribes to UVEEventType.CONTENT_CHANGES.
  2. In the editor, add or remove a contentlet.
  3. Observe (raw message listener): bounds/scroll/selection events arrive; uve-set-page-data / uve-reload-page never do. Canvas doesn't update until manual refresh. No console warning anywhere.

Verified against @dotcms/uve / @dotcms/types 26.7.21-1 with a 26.07.06-3 backend, with a custom rendering layer (no @dotcms/react/@dotcms/angular).

Expected
  1. Warn loudly when a headless client sends CLIENT_READY without graphql.query — editor console (and ideally an editor UI hint): "client registered without a page query; content-change events will not be delivered. Pass the full client.page.get() response to initUVE()."
  2. Document and formally deprecate the params-only shape: state in the @dotcms/uve docs/migration guide that initUVE() expects the full DotCMSPageResponse (whose graphql field registers the client for CONTENT_CHANGES/PAGE_RELOAD delivery), and that the beta-era { params } shape is legacy/unsupported.

(Optional, for triage discussion: a lightweight invalidation signal for query-less clients was considered, but since the supported path — passing the full client.page.get() response — registers the query automatically, warning + documentation likely covers the real-world cases.)

Workaround / correct usage

Fetch via @dotcms/client's client.page.get() and pass its entire response to initUVE(pageResponse) — the response carries the graphql metadata, so registration happens automatically. Framework packages (useEditableDotCMSPage in React/Vue, DotCMSEditablePageService in Angular) do all of this internally, as shown in the official examples (examples/nextjs, examples/angular).

Links

Contributor guide

Open the contributing guide

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 with the CLIENT_READY handler in dot-uve-actions-handler.service.ts and the $handleReloadContentEffect gate in edit-ema-editor.component.ts; trace how query-less clients become ready without requestMetadata. Review the SDK public types and the UVE documentation or migration guidance mentioned in the issue. Done means params-only registration is clearly warned about and the supported full-page-response usage is documented, with behavior covered by relevant tests if present.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
documentation, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.