Make hemx-build diagnostics and the documented .heml syntax surface the authority for any editor overlay, while rejecting a second template language, selector model, formatter, or custom editor framework. req: diagnostics/004
6.9 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.hemlfiles 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-buildcovers 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_failcovers 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-jscovers root-scoped runtime behavior, selectorless targeting, fingerprint mismatch refusal, SSE application, and recoverable runtime events.cargo test -p hemx-test --test examples_contractkeeps 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 health --strict on a clean tree. req: test/003 req: test/004