# 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`/`hemx::Form`/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`, or `Vec` 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 ` / `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