Files
hemx/docs/diagnostics.md
T

7.1 KiB

Diagnostics guide

hemx diagnostics should tell a Rust developer which template fact, generated helper, or handler shape is wrong, and what to change next. They should not teach raw ids, selector targeting, runtime opcodes, or Cargo internals in the normal path. req: diagnostics/001 req: diagnostics/002 req: diagnostics/003

Use this guide as the v1 checklist for common mistakes in beginner and production-shaped apps. Structured hemx-build diagnostics expose a file path, directive, target, expected template fact, and repair action so an optional editor overlay can share compiler authority without becoming a custom editor framework.

Where errors happen

  • Template/build diagnostics come from hemx_build::app().run() while reading .heml files and CSS. Fix the template or generated-surface convention.
  • Derive/compile diagnostics come from #[hemx::surface], #[hemx::form], #[hemx::handler], #[hemx::component], and #[hemx::app]. Fix Rust code so it matches the generated surface.
  • Runtime diagnostics come from the tiny browser runtime when a deployed page and response are incompatible or a target cannot be applied. Fix deployment or recover with a full page response. req: failure/005

Common mistakes and fixes

Mistake Diagnostic shape Fix
Handler has no matching template handle unknown hemx handle \save`; add `data-hemx-handle="save"`` Add the handle to the template, rename the function, or put the handler in the matching component.
Component is missing a generated handler #[hemx::component] missing handler implementation(s): delete Add a #[hemx::handler] fn delete(...) in that component, or remove the template handle.
Handler name is ambiguous across components ambiguous generated handle name(s): save Scope the component with #[hemx::component("todos")] or rename handles so the generated path is unique.
Handler misses generated params hemx handler \show` is missing generated param argument(s): mode` Add typed handler arguments for every data-hemx-param-* fact generated by the template.
Form handler omits the form argument handles a generated form and must accept a typed form argument Accept Form<NewThing>/hemx::Form<NewThing>/integration equivalent and derive #[hemx::form("...")] for the type.
Form struct misses a control hemx form \new_todo` is missing field `title`` Add a Rust field matching the form control name, or rename the template control.
Required/multiple form control has wrong Rust shape required ... must not be Option<_> or accepts multiple values and must be Vec<_> Match HTML required/multiple semantics with T, Option<T>, or Vec<T> as appropriate.
Form field type cannot parse submitted values compiler mentions T: FormValue / T: hemx::FormValue Implement FromStr/the expected form value trait for the domain newtype, or use a parseable domain type.
Generated resources are unavailable could not find generated hemx module / could not find generated hemx symbols plus add hemx_build::app().run()? to build.rs Add or fix build.rs, then rerun cargo check; do not copy $OUT_DIR paths into app code.
Unknown data-hemx-* attribute unknown hemx attribute ... check the spelling or use a non-hemx data-* attribute Fix the spelling, use the supported hemx attribute, or rename app metadata to a non-hemx data-* attribute.
Selector-style targeting ``data-hemx-target is selector-style targeting; hemx uses generated resources Put data-hemx-slot on the local target and return a generated slot/page/form effect.
Generated target appears in a loop without a stable key inside an h-for without h-key; add a stable h-key="item.id" Add a stable h-key to the owning loop; use generated keyed helpers for row updates.
Page/SSE attributes are on the wrong element expected a real <a href=...> / expected placement on the same element as data-hemx-root Keep page navigation on anchors and put root-scoped runtime attributes on the root element.
Result handler error type is not mappable compiler reports the error type does not satisfy IntoHandlerFailure Implement IntoHandlerFailure for the app error, or keep expected validation as generated UI effects instead of Err. req: failure/004
Old page talks to a new server/runtime runtime refuses the partial update on fingerprint mismatch Serve a self-consistent release or fall back to full page reload/navigation. See docs/recipes/deploy-versioning.md. req: abi/004
Missing runtime target runtime emits a missing-target diagnostic in development and fails/no-ops according to target kind Fix the template/generated helper mismatch; do not retarget with selectors. req: failure/001

What a good diagnostic should include

A v1-quality diagnostic should include:

  • the user-facing name: handle, form, slot, key, param, class, event, or template
  • the source area: template path, Rust item, or deployment/runtime boundary
  • the concrete expected shape, not an internal representation
  • one next action that preserves generated helpers and the tiny runtime

Avoid beginner-facing messages that suggest ResourceId, ResourceRef, raw Effect, manual registries, selector strings, or runtime opcodes. If an advanced escape hatch is genuinely required, say that it is advanced and name the safer normal path first. req: public_api/002 req: public_api/005

Editor overlay boundary

A .heml editor overlay is optional and subordinate to the compiler. It may read docs/hemplate-syntax.md, run or reuse hemx-build diagnostics, and present compiler-shaped diagnostics, completion, hover, and navigation for documented syntax and generated targets. It must not define a second template language, formatter, selector targeting model, JavaScript expression layer, or custom editor framework. If editor feedback disagrees with hemx-build, hemx-build wins. req: diagnostics/004

Verification anchors

Current recurring checks cover the most common classes:

  • cargo test -p hemx-build covers template/build diagnostics such as unknown hemx attributes, selector-style targeting, invalid runtime attribute values, missing keys, and invalid page/SSE placement.
  • cargo test -p hemx-derive --test compile_fail covers derive/compile diagnostics for missing handlers, form mismatch, params, missing generated files, unknown scoped components, ambiguous handles, and generated resource lookup.
  • cargo test -p hemx-js covers root-scoped runtime behavior, selectorless targeting, fingerprint mismatch refusal, SSE application, and recoverable runtime events.
  • cargo test -p hemx-test --test examples_contract keeps public examples from teaching forbidden normal-path constructs.

Before claiming the diagnostics story is closed for v1, run those gates plus cargo run -p hemx-xtask -- test, cargo check --workspace, and redgate refs on a clean tree. The installed CLI's health mode additionally requires every historical row to use its newer prescriptive wording, which is not the elected compatibility gate for this corpus. req: test/003 req: test/004