Diagnose controls rendered as text
A control displayed as its own description, such as StackControl { … }, reached the
escaped-text fallback after every registered view map declined it. Loading a view assembly is
not proof that its map was registered, and registering a map is not proof that it accepted
the particular control or skin.
The diagnostics answer those questions separately:
MeshWeaver.Blazor.Views.ViewsExtensionsrecords DefaultViews registered on hub at Information when the layout client aggregates its configuration. The structured fieldsAddress,MvidandCountidentify the hub, the exact view assembly and the map count.MeshWeaver.Layout.Client.ViewDispatchrecords the platform warning when no map accepts a control. The registered map owners identify which contributors were consulted.MeshWeaver.Blazor.Components.DispatchViewrecords through the escaped-HTML fallback at Information for an actual fallback render, namingArea,ControlTypeandHubAddress. Ordinary view dispatch remains at Debug. Unknown-skin details remain at Debug as well./healthincludesview_packs, with the registeredowners,countand roothub. An absent default pack is Degraded: controls that need that pack may fall back, while other packs can still render their controls. An absentILayoutClientis different: controls cannot be dispatched at all. Neither case is reported as a successful render.
The registration event runs once per layout-client aggregation, not on every control. The fallback event is limited to failed view selection. These are persistent operational signals whose value is diagnosing a visible rendering defect; they are not a temporary increase in general render logging. They do not change the health endpoint's readiness behavior.
Which hub is measured
Module HubConfigurations install the view maps on the root mesh hub. Ordinary portal circuit
hubs inherit its service scope, so DispatchView resolves the root ILayoutClient; the health
check reads that same registration. A circuit with its own layout-client registration needs
separate investigation: the root health result does not establish which maps that circuit uses.
Descriptor consumers
The fallback descriptor includes HtmlView.IsFallback, a real Blazor component parameter.
Consumers can forward the entire parameter bag, including that flag, without a special filter.
The flag only identifies the rendering path; it does not alter the content or its encoding.
The initial implementation put the flag in the parameter bag but stripped it only inside
DispatchView. A direct descriptor host forwarded it to an HtmlView that did not declare
the parameter and threw an unmatched-parameter exception. A real HtmlRenderer regression
reproduced that failure; another regression reproduced the misleading no-layout-client
health message. Registration and fallback tests also capture the event category, level and
structured fields, and verify that a normal HTML view emits no fallback event.
These diagnostics do not repair a missing view map, an incompatible module, or a node whose latest compiled assembly was refused by its consumer. They provide the evidence for identifying that defect. A healthy registration check alone must not be used to claim the affected page works.
A render pack that never reached the installation
The packs that render the platform's own pages — EntityViews (every text, number, date and
choice input), GraphViews (the picture upload, MeshNode picker, card and content editor), Chat
(the composer) and the collaborative markdown editors in Essentials — are registry packages, not
image entries. An installation receives them only through its install pass, and that pass has two
lanes: the registry's preInstalled baseline, and the packages the deployment names in
PluginCatalog:InstallByDefault (its record's preInstall) together with their requires.
A list that names packages exactly is an explicit set (core policy declared-package-set-is-exact):
the baseline lane is off and only the named packages and their dependency closure install. So
the render packs must be in the closure of what an installation names, not only in the baseline.
Essentials — the package new installations pre-install — therefore requires EntityViews,
GraphViews and Chat, and Memex.Hosts.Test →
ViewPackDeliveryPathTest.AnInstallThatDeclaresOnlyEssentials_StillReceivesEveryRenderPack reads
the repository's package roots and fails when the closure stops reaching one of them.
Measured 2026-10-17 on a freshly provisioned customer installation whose record pre-installs Essentials alone. Nothing errored and the pods were ready. The readings that named the defect:
- The
view_packshealth entry wasDegraded: the entity-views pack did not register on this hub … the graph-views pack did not register on this hub, with two maps registered (MeshWeaver.Blazor.Views:AddDefaultViews,MeshWeaver.Blazor.Portal:UserProfileControl→UserProfilePageView). MeshWeaver.Layout.Client.ViewDispatchlogged no view map accepted TextFieldControl … in area Settings/1/1, then the same forNodeImageUploadControl,MeshNodeContentEditorControlandMarkdownEditorControlinEditProfile/…areas, andThreadChatControlinComposer.- No module-landing line ever named EntityViews, GraphViews or Chat. Essentials' own closure (AI,
the providers, Export, Mcp, Notifications, Markdown.Collaboration) landed, but each landing said
RESTART REQUIRED to load it, and
pending_module_activationlisted them as landed and not loaded.
The Settings → Profile page painted TextFieldControl { Id = , … } where the display-name field
belonged, while its headings, nav and back arrow (all default-pack controls) rendered normally.
Three gates now cover this failure:
SettingsProfileRenderTest(MeshWeaver.Blazor.Views.Test) renders Settings → Profile and the profile editor through the real Blazor renderer, using exactly the packs Essentials' closure delivers. It waits until every section's own view has rendered, it fails on a render that never settles, and it fails on any visible text that matches a control's recordToString().SettingsProfileWithoutCollaborationViewsTestis its negative control: without the markdown editors' pack, the Bio and Links sections must printMarkdownEditorControl { Id = … }.scripts/examples-smoke.pysmokes the smoke identity's Settings tabs (the built-in ones and every tab its menu links) and marks a frame string that matchesRECORD_TOSTRINGred.- The browser half (
e2e/examples-smoke.spec.ts) marks visible text that matches the same pattern red. The dump exists only in the browser, because the server frame carries the typed control.