---
title: "Diagnostics"
description: "Every diagnostic code Hem can report, with its title and explanation."
image: "https://hem.run/social/hem.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://hem.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Diagnostics

Hem reports 121 diagnostic codes. Each one is registered once, with the title and
explanation below, and reaches you through three surfaces: rendered CLI output, editor
diagnostics through the language server, and `hem explain <code>`.

This page is generated from the compiler's diagnostic registry, so it always matches the
codes the installed compiler can actually report.

## Syntax

Lexer and parser diagnostics. These report before any type information exists.

### HEM1001

unterminated string literal

Hem string literals open and close with `"` on a single line. If you need a line break inside a string, use a template literal with backticks instead.

### HEM1002

unterminated block comment

Block comments open with `/*` and close with `*/`. The lexer reached the end of the file while still inside this comment.

### HEM1003

unexpected character

This byte is not part of any Hem token. It usually means a typo, a paste from a different language, or a Unicode look-alike character.

### HEM1004

expected an expression

Something that produces a value must appear here: a literal, a name, a call, a `match`, an `if`/`else`, or a parenthesized expression.

### HEM1005

expected a binding name

Bindings introduce a name before the rest of the construct continues: `let total = price * count`, `use handle = open()`, or `for item in items { ... }`. A binder is an identifier or a destructuring pattern; a parameter may also carry an optional marker (`x?: T`) or be a rest element (`...xs: T[]`). Reserved keywords such as `from` cannot be binding names or field names in record binding patterns, even when the field is aliased. Choose a non-reserved binding name and read reserved properties separately: `let sourceId = record.from`. The contextual keywords `type` and `error` can be ordinary binding names.

### HEM1006

expected `=` after the binding name

Every binding takes an initializer: `let name = expression` or `use handle = expression`. Hem has no uninitialized bindings.

### HEM1007

expected a statement

Statements begin with a keyword like `let`, `use`, `type`, `error`, `return`, or an expression. This token cannot begin a statement.

### HEM1008

unterminated template literal

Template literals open and close with backticks. A `${ ... }` hole contains a full Hem expression, and nested template literals must close before the outer template can continue.

### HEM1009

unterminated regex literal

A regex literal starts with `/` only in expression-operand position. Character classes and escapes are part of the regex body, but the literal must close before the end of the line.

### HEM1010

unclosed delimiter

Delimited syntax must close the delimiter it opened. The parser keeps the recovered region in the tree so formatting and diagnostics can continue after the missing delimiter.

### HEM1011

unparenthesized unary operand before `**`

Hem follows JavaScript's exponentiation rule: `-a ** b` is rejected because the unary expression must be parenthesized as `(-a) ** b`.

### HEM1012

`??` mixed with `&&` or `||`

Hem keeps JavaScript's nullish-coalescing restriction. Parenthesize the logical expression or the coalescing expression to make the grouping explicit.

### HEM1013

ill-delimited TypeScript type extent

Type syntax is extent-scanned in `@hem-lang/syntax` and parsed later by TypeScript. When brackets or delimiters do not balance, Hem clamps the raw type extent at a safe boundary and continues parsing.

### HEM1014

assignment in expression position

Hem intentionally keeps assignment out of the expression precedence table. Write `target = expression` as its own statement, or bind a new value with `let name = expression`.

### HEM1015

retired: generic arrow type parameters were deferred

Retired in M0.11. Generic arrows now parse when the type parameter list uses the TSX-compatible `<T,>` spelling or an `extends` bound; `<T>(x) => x` is JSX and reports the A.8 teaching diagnostic instead.

### HEM1016

expected `in` in for loop

A `for` loop names one binder and then the iterable expression: `for item in items { ... }`. The `in` keyword separates the binder from the loop source.

### HEM1017

expected loop body

Loops run a block. Write `for item in items { ... }` or `while condition { ... }` with the `{ ... }` body on the loop statement.

### HEM1018

missing binding initializer

Every `let` or `use` binding has the shape `name = expression`. Hem has no uninitialized bindings, so the expression must appear after `=`.

### HEM1019

`and` without binding group

The `and` keyword is a statement-level separator inside binding groups: `let a = one and b = two`. Start the group with `let` or `use` before adding `and` members.

### HEM1020

missing same-line operand

`raise` and `throw` take a same-line operand: `raise problem` or `throw error`. A value on the next line starts a new statement, so it is not the operand.

### HEM1021

expected `=>` after pattern

Match and catch arms separate the pattern from the arm body with `=>`: `| Ok(value) => value`. The pattern stays to the left of the arrow, and the expression or block to run stays to the right.

### HEM1022

expected an arm body

An arm body is either an expression or a `{ ... }` block. Write `| pattern => expression` for a value arm, or `| pattern => { statements }` when the arm needs statements.

### HEM1023

catch guards are deferred

Catch arms currently dispatch only on the error pattern. To branch by an extra condition, catch the wider pattern, use `match` inside the arm, and `raise` the original error in the fallback arm: `| err => match err { | Specific => handle() | _ => raise err }`.

### HEM1024

expected variant member

A variant member starts with a name and may carry one parenthesized payload: `type Result = | Ok(T) | Err({ message: string })`.

### HEM1025

unclosed match body

A `match` expression opens its arm list with `{` and closes it with `}`. Each arm stays inside that body: `match value { | pattern => result }`.

### HEM1026

unclosed class body

Hem keeps class bodies as raw interop regions in this milestone, but the outer `{ ... }` still has to balance so the parser knows where the class declaration ends.

### HEM1027

unclosed service body

A service declaration opens its member list with `{` and closes it with `}`. Service members stay one per line inside that body: `service Api { get: Request => Response }`.

### HEM1028

malformed import form

Imports use the JavaScript module shapes: `import "side-effect"`, `import name from "module"`, `import { name as alias } from "module"`, or `import * as ns from "module"`. `import type`, `import defer`, `import source`, and trailing `with { ... }` attributes use the same module-source position.

### HEM1029

mismatched JSX closing tag

A JSX element must close with the same tag name it opened: `<Card>...</Card>`. Member tags compare by their full dotted name, so `<Foo.Bar>` closes with `</Foo.Bar>`.

### HEM1030

unclosed JSX element

A non-self-closing JSX element must eventually close. Use `</Tag>` for elements, `</>` for fragments, or write the opening tag as self-closing with `/>`.

### HEM1031

unbraced JSX attribute value needs delimiters

Unbraced JSX attribute values admit literals and postfix chains only. JSX's `>` and `/` are tag closers, so binary and unary operators would be ambiguous: write `n={a + b}` or `n=(a + b)` instead of `n=a+b`.

### HEM1032

generic arrow needs a trailing comma

In expression position, `<` starts JSX. Hem follows TSX: a generic arrow must disambiguate its type parameters with a trailing comma, as in `<T,>(x: T) => x`, or with an `extends` bound.

### HEM1033

expected JSX attribute or tag end

Inside a JSX opening tag, write an attribute name, `name?`, `name=value`, a spread `{...value}`, `>`, or `/>`. A bare name is a pun that passes the in-scope binding; write `name={true}` for a literal boolean true.

### HEM1034

block after `let`–`else`

`let`–`else` is not an `if`/`else`. Its `else` runs one diverging statement — `return`, `throw`, `raise`, `break`, or `continue` — directly, with no surrounding `{ }`. Write `else return 0`; a block here would be read as an object literal, which cannot diverge.

### HEM1035

increment and decrement are removed

Hem removes `++` and `--` in both their prefix and postfix forms: their value-versus-effect duality hides a mutation inside an expression. Increment a `let mut` binding with a compound assignment statement — `x += 1` or `x -= 1` — on its own line. A space keeps the unary operators apart, so `a + +b` still parses as addition of a unary plus.

### HEM1036

`const` binding is removed

Hem's `let` is TypeScript's `const`: it declares a binding that cannot be reassigned. Write `let name = value`, including for destructuring and exported bindings. Use `let mut` when the binding needs reassignment; it compiles to TypeScript's `let`.

### HEM1037

`var` binding is removed

Hem bindings are block-scoped. Replace `var` with `let mut` to allow reassignment, or use `let` when the binding is never reassigned. The quick fix uses `let mut`; it does not preserve JavaScript's function-scoped hoisting.

## Language

Hem's own semantic rules: absence, matching, bindings, operators, and declarations.

### HEM2001

boundary any demoted

Hem does not let `any` silently disable checking. A value whose inferred TypeScript type contains `any` is emitted with an `as unknown` boundary cast. Narrow it with a predicate, schema parser, or explicit safe cast before using it.

### HEM2002

boolean value required

Hem conditions and logical operators accept only booleans, so JavaScript truthiness cannot leak `0`, an empty string, or another accidental falsy value into control flow. Write an explicit comparison such as `items.length > 0`, `value != None`, or `ready == true`.

### HEM2003

double optional type

Hem's `?T` expands to `T | null | undefined`, an unboxed nullable. Applying the `?` prefix twice would produce the same union, so a literal `??T` is rejected rather than silently collapsed. Instantiating a generic `?T` with an already-optional argument does collapse silently; only spelling the double prefix by hand is an error. Write `?T` for a single optional, or `Option<T>` when you need a boxed optional that can itself be absent.

### HEM2004

bind outside effect block

Postfix `!` is Effect's bind operator, not TypeScript's non-null assertion. An optional read needs absence handling: capture the read and check it, provide a fallback, or establish a stronger input contract. Preserve when and how often the read executes. For a Promise, await it in an async context; awaiting does not itself establish that the resolved value is present. For Effect operations in collection callbacks, compose them with `Effect.forEach` and bind the resulting Effect in the enclosing effect block. This diagnostic is reported before operand types are checked, so its guidance is conditional and has no automatic rewrite.

### HEM2005

pattern usefulness

A match with missing cases or an open constructor set can fall through without a value, so HEM2005 refuses it; tuple scrutinees name missing combinations in universe order, capped at three plus a count. For a closed constructor set, add explicit arms so future cases require another decision; an intentional catch-all remains legal but also handles new cases without another missing-case diagnostic. An open constructor set requires a fallback for values outside the known cases, and guarded arms never establish exhaustiveness because their guards may reject every value. A redundant arm is a warning because it is dead but does not change the result. An unknown constructor names a case the matched type does not have, usually a misspelling; correct the name rather than widening the match.

### HEM2007

group member references a sibling binding

An `and` group is simultaneous: every initializer starts before any of the group's names are bound. Hem does not infer a dependency graph because data dependency does not define effect order — a rate limiter, for example, must stay explicit — and an edit must not silently serialize a formerly concurrent group. Write the dependency as a separate binding first, then start the independent group: `let shared = make(); let a = consume(shared) and b = other()`.

### HEM2008

inconsistent binding group

Binding groups use one execution shape. Plain groups evaluate left to right, `await` groups start promises together, and effect-world `!` groups arrive with the M4a extension. Core `use` is not grouped because a partially failed concurrent acquisition can leak without scope semantics; write separate `use` statements until extension-world scoped groups are available.

### HEM2009

nested bind inside a group member

`await` groups are for flat concurrent starts: `let a = await fa() and b = await fb()`. A nested `await` or postfix `!` inside an argument creates a waterfall before that member can enter `Promise.all`. Bind the inner result first, then use it from a later binding or group member.

### HEM2010

forbidden surface type

Hem keeps `any` out of source type positions. Use `unknown` for unchecked values and narrow before use. Exact `T | null` and `T | undefined` types are writable and pass through to TypeScript; `?T` expands to `T | null | undefined` and therefore admits both absence values. Writing a nullish type does not permit a `null` or `undefined` value literal or an unchecked assertion.

### HEM2011

catch tag is not an error class

Core named catch arms dispatch with `instanceof`, so each named tag must resolve to a class derived from `Error`. Effect catch arms must name a tag in the checked error channel. If TypeScript exposes `any` for the caught expression, give it a known type so Hem can check the arm. For core catches, use a declared Hem `error`, import an `Error` subclass, or write a binding arm such as `| cause => handle(cause)` for an untyped thrown value.

### HEM2012

use value is not a resource

Core `use` registers cleanup at block exit and therefore requires `Disposable` or `AsyncDisposable` evidence from TypeScript. Ordinary values belong in `let`; resources without the protocol can be wrapped with a library adapter or `DisposableStack`.

### HEM2013

assignment needs a mut binding

Hem bindings are immutable unless their declaration includes `mut`. Prefer shadowing with a new `let` when computing a new value; use `let mut name = initial` only when the algorithm genuinely needs in-place assignment.

### HEM2014

let-else branch must diverge

A refutable `let` only makes its bindings available after the pattern succeeds. Its `else` branch must leave the current control-flow path, so write `return`, `throw`, `raise`, `break`, or `continue` instead of a value-producing expression.

### HEM2015

component name is already claimed

Exported top-level PascalCase arrow bindings that produce JSX keep their authored emitted name so React Fast Refresh can identify them. Two such components cannot share one name; rename one component instead of relying on Hem's ordinary shadow suffixes.

### HEM2016

pattern bindings must be unambiguous

A successful pattern introduces each name exactly once. In an or-pattern, every alternative must introduce the same names so the arm or binding has one stable scope regardless of which alternative matched. Rename duplicate bindings or make the alternatives bind the same set of names.

### HEM2017

variant payload has multiple positionals

A variant constructor carries either a single positional payload (bound to `value`) or a record whose fields spread onto the discriminated union. Several positional fields have no field names to spread and no stable accessor, so they are rejected permanently rather than deferred. Rewrite the payload as a record: `Rect({ w: number, h: number })`.

### HEM2018

unused expression result

Hem refuses effect-free expression statements and unused calls or `await` results whose checked type is `Effect`, `Promise`/`PromiseLike`, canonical `Option`/`Result` from `@hem-lang/std`, or the configured transport's boxed `Option`/`Result`. Await or return a Promise or handle its rejection; compose or return an Effect or run it at a runtime boundary, using postfix `expression!` inside an `effect` block. Handle Option/Result cases with `match`, or use postfix `!` in an effect block to propagate absence or failure; prefix `!` is boolean negation. Ordinary side-effecting calls (`array.push`, `map.set`, `console.log`) and `?T` results remain legal. `let _ = expression` deliberately evaluates and discards the result without running an Effect, handling a Promise rejection, or inspecting carrier cases; `let _ = expression!` runs an Effect here and discards its success value.

### HEM2019

tuple-scrutinee arm shape

`match [a, b]` is multi-scrutinee syntax: the bracketed elements evaluate to independent values and each arm is a fixed-length array pattern with one column per scrutinee. No runtime tuple is materialized, so a rest element, an `as` over the whole array pattern, or a length mismatch has no meaning. Write one `[…]` pattern per arm, using per-column or-patterns (`[A | B, C]`) for alternatives and per-column `as` for bindings.

### HEM2020

brand declarations cannot be generic

A `brand` declaration mints exactly one identity constructor for one fixed base type. Hem does not support a generic brand family parameterized by `<T>` in v1. Write a concrete, non-generic brand for each base type you need, or drop `brand` and declare an ordinary generic type alias instead.

### HEM2021

non-numeric + operand

Hem's `+` is arithmetic only: both operands must check as `number`, or both as `bigint` — never a mix, and never a string. String concatenation has exactly one spelling, a template literal, so a stray numeric value can never silently paste itself into a string and a string can never silently become `NaN` in an arithmetic expression. `+=` follows the same rule as `+`. Unary `+` narrows further and requires an already-`number` operand, since it is a coercion in disguise; spell the coercion explicitly with `Number(x)` instead. Building a string across a loop can use a parts array joined with `.join("")` rather than repeated `+=`.

### HEM2022

while-let needs a refutable pattern

`while let` re-tests a refutable pattern each iteration and ends the loop when it fails, the way `let`–`else` ends the path by diverging. A pattern that always succeeds — a bare binding, `_`, or a record/array of only bindings — never fails, so the loop would spin forever. Bind the value with an ordinary `let` inside a `while <condition>` loop, or match on a refutable shape like `Some(value)`.

### HEM2023

deriving Eq target not derivable

`deriving Eq` recurses into a field only when its type is something the compiler can already compare structurally: a primitive, an array, `?T`, a brand, or another Hem type that itself `deriving Eq`s. A field typed as a Hem variant or `error` without `deriving Eq` is refused rather than silently compared by reference, because the compiler already knows its shape and a silent reference comparison there would hide a real difference. A genuinely foreign type — an imported class, `Date`, `RegExp` — has no such comparator to call, so it compares by reference without a diagnostic; that is `deriving Eq`'s documented, structural-only boundary, not an oversight. Add `deriving Eq` to the named type, or don't derive on the type holding it. Only `Eq` is a recognized derivation in this version; any other `deriving` name is refused until that derivation ships.

### HEM2024

framework directive is outside the module prologue

Hem preserves top-level JavaScript directive prologues byte-for-semantics in emitted TypeScript. React's `use client` and `use server` directives only define a module boundary when they precede every import, declaration, and executable statement; writing one later would emit an inert string expression, so Hem diagnoses the placement instead of silently changing framework behavior.

### HEM2025

ambiguous carrier constructor

Capitalized `Some`, `None`, `Ok`, and `Err` are contextual vocabulary shared by nullish values, canonical carriers from `@hem-lang/std`, and configured Effect carriers. Bare `None` infers undefined; other constructors need a checked expected carrier rather than guessing their runtime shape. Contextual `Some`, `Ok`, and `Err` each take exactly one positional argument, giving each constructor one unambiguous payload. Add an annotation when contextual syntax is useful, or use the canonical qualified constructor explicitly. Nullish `Some(value)` emits the value unchanged, so a nullish payload remains absent; choose boxed `Option<Option<T>>` when nested absence must stay distinct.

### HEM2026

unsound carrier binding

Carrier binding is checked control flow. Hem propagates the original `None` or `Err` only from a native `?T` or a canonical carrier from `@hem-lang/std`, and only when that residual fits the nearest propagation boundary of the same representation: an arrow return or an effect block's success channel. Foreign lookalikes, implicit cross-carrier conversion, and nested refutable payloads require an explicit `else` or `match`.

### HEM2027

nullish Effect lift without policy

Postfix bang can adapt canonical `Result` and `Option` carriers from `@hem-lang/std` because `Err` carries an error and the configured Effect transport defines `Option`'s missing-element error. Native `?T` carries neither. Hem refuses to invent application policy; use an explicit pattern and raise the domain error you intend.

### HEM2028

unchecked type assertion

Hem assertions may widen an already checked value, but cannot manufacture a narrower type. Imported declarations remain trusted boundaries; unchecked assumptions require a reviewed TypeScript shim.

### HEM2029

unchecked predicate signature

Imported validators remain trusted contracts. Hem does not verify an explicitly authored `is` or `asserts` signature against its implementation; use checked narrowing and result values instead.

### HEM2030

unsafe writable alias

Readonly access cannot silently become writable access. A mutable alias must preserve the source value's read and write contract; a shallow copy does not isolate nested values.

### HEM2031

invalidated property refinement

A readonly view does not prove that another alias cannot mutate the object. Capturing an object reference does not preserve its property refinements. Moving a read earlier can change behavior, so this diagnostic provides no automatic edit.

### HEM2032

type-view expression used as a write target

A checked widening assertion or conformance check describes a value, not permission to replace its storage. Using it as a write target can bypass constant bindings, readonly properties, and the original location's accepted type.

### HEM2033

unsafe tuple mutation

A tuple's required positions and slot types must survive writes through every supported authored alias. Destructive methods and writes that cannot preserve that contract are refused; readonly views do not copy the tuple. Compatible element replacement and rest appends remain available.

### HEM2034

raise of a bare error constructor

Raising a class does not construct an error: core catch arms and Effect catchTags expect instances. Hem inserts `new Name()` for `raise Name` only when Name is an unshadowed, locally declared error with no fields. Local errors with fields use `raise Name({ … })`, which inserts `new`. Other constructor-only values, including imported error classes and class-valued properties, require explicit `raise new Name(…)` in both worlds.

## Project and tooling

Configuration, emit targets, and constructs the compiler does not yet lower.

### HEM3001

Effect extension is incompatible

The Effect extension probes every runtime and type capability its generated code relies on before lowering starts. Upgrade the configured package to the supported Effect 4 cohort or point `effectImportSource` at one that exports the complete contract; Hem reports the mismatch once instead of exposing a cascade from generated TypeScript.

### HEM3002

emit target collides with a handwritten file

Sibling emit writes `foo.ts` next to `foo.hem` (ADR 0005). A file without the generated-from banner is treated as handwritten and never overwritten; rename one of the two files.

### HEM3003

construct is not emittable yet

Rather than guess at a lowering, the compiler refuses the whole file when it meets a construct it does not yet emit. The message names the construct and, where available, a supported alternative. Awaited binding groups require annotations on every member or none; annotating every member retains concurrent evaluation. Range loops bind a single number; destructure ordinary iterable values instead. An intentional wildcard discard uses unmodified `let _ = value`; use a named binding for annotations, mutation, or recovery. Constructs rejected on principle carry their own permanent diagnostic instead of this one.

### HEM3004

TypeScript project is not ready

Hem uses the real TypeScript project for module resolution, libraries, JSX, and supporting files. It overlays its required strictness only inside Hem's private no-emit checker, so the application build need not adopt those options at once. Add or repair the reported project configuration, then run `hem check` again.

### HEM3005

formatter output diverged

The formatter reparses its own output and compares it to the input before returning it. When the two parse trees differ — a dropped comment, an unbalanced delimiter, a reordered token — it refuses the edit and hands back the original bytes so a formatter defect can never silently corrupt a program. Please report the input that triggered this.

### HEM3006

incompatible standard carrier package

Hem grants contextual constructors, must-use behavior, carrier binding, and Effect adapters only to the canonical `Option` and `Result` carriers from `@hem-lang/std`. Those features depend on the standard carrier shapes and operations matching this Hem release. Align the Hem and `@hem-lang/std` versions rather than patching structural lookalikes.

### HEM3007

construct is not emittable by design

This construct is refused on principle rather than pending support, so reworking the code is the only path forward — the message names the rule that rules it out. Constructs that merely await a lowering report HEM3003 instead.

### HEM3008

generated sibling was edited

Generated siblings carry a hash of their body in the banner. Build, watch, and Vite refuse to overwrite or remove a sibling whose body no longer matches; `hem check` reports the same error without writing. Move the change into the .hem source, then run `hem build --overwrite-edited` or delete the sibling and rebuild. The flag discards edits to generated siblings, including stale siblings, and reports each overwrite or removal. It is only available for one-shot builds, cannot be combined with --watch, and never overrides handwritten-file collisions (HEM3002). Watch and Vite rebuild when a known sibling is deleted or a refused sibling changes. CRLF and LF line endings are equivalent. Older banners without a hash remain overwritable and gain a hash on the next build.

## Effect

Safety rules for the optional Effect extension. None of these can report unless `hem.effectImportSource` is configured.

### HEM4102

Effect requirements are not provided

Every `!` records the Effect requirement channel at its authored site. Supply the listed services with `Effect.provide` or a Layer before calling a runner; the related locations show exactly where each requirement entered the program.

### HEM4103

effect bind crosses a function boundary

A generator yield belongs to the nearest `effect` or `resource` block. A callback creates another function, so a `!` inside it cannot yield from the surrounding block. For collections, use `Effect.forEach(items, (item) => work(item), { concurrency: 5 })!`; for one callback, return an Effect and bind it outside the callback.

### HEM4105

scope-bearing Effect must use use

A plain postfix `!` can let a scope-bearing acquisition escape without making ownership visible. Bind it with `use` inside an `effect` or `resource` block: `let lease = acquire()!` becomes `use lease = acquire()`. `effect` owns and closes the scope, while `resource` passes Scope to its caller.

### HEM4106

nested effect runner

Calling an Effect runner inside an effect block starts a separate execution boundary. That child loses the surrounding services, supervision, test clock, interruption scope, and tracing context. Compose the child Effect with postfix `!`; at a genuine application edge, keep the runner outside the effect block. An explicitly captured Runtime is the visible escape hatch when a separate run is deliberate.

### HEM4107

multiple effect provide boundaries

Repeated `Effect.provide` on one Effect can build and close related Layers in separate lifecycles, duplicating acquisition or breaking sharing. Compose dependencies with `Layer.provide` and combine independent outputs with `Layer.merge`, then use one application-edge `Effect.provide`.

### HEM4108

dependent layers in Layer.mergeAll

`Layer.mergeAll` is for independent Layers. When one Layer requires a service another Layer builds, merging them as peers does not preserve dependency order or sharing. First pipe the dependent Layer through `Layer.provide(provider)`, then merge that closed composition with genuinely independent Layers.

### HEM4109

leaked service requirements

A service method should expose the capability promised by its `service` declaration, not the dependencies used to implement its live Layer. Bind implementation services while constructing the Layer so returned methods are closed over them. If a dependency is genuinely request-local and caller-provided, include it explicitly in the method's Effect requirement channel.

### HEM4110

unsafe public effect channel

An exported Effect promises callers a typed failure channel and a complete service requirement set. `any` or `unknown` in either channel makes that promise unverifiable. Validate an imported untyped value once and assert it from `unknown` to a concrete Effect type at the import boundary; do not weaken every downstream declaration.

### HEM4111

narrowed effect carrier channel

Type assertions must not claim an Effect has fewer possible successes, failures, or service requirements than its checked value. Such a cast can hide an unhandled failure or missing service without changing runtime behavior. An imported `unknown` may be asserted once to a concrete Effect contract as an explicit boundary; assertions between two recognized Effect types may widen channels but never narrow them.

### HEM4112

defer outside effect scope

A deferred cleanup must belong to a visible Effect Scope. Put it inside `effect {}` when the block should own and close that scope, or inside `resource {}` when the caller should provide Scope. Ordinary synchronous blocks have no Effect lifetime to attach the finalizer to.

### HEM4113

defer cleanup type mismatch

`Effect.addFinalizer` cannot report a typed cleanup failure after the surrounding scope has already chosen its result. Hem therefore accepts only an existing `Effect<void, never, R>`: synchronous work must be lifted explicitly with `Effect.sync`, returned values must be discarded explicitly, and typed failures must be handled before `defer`. Exit-sensitive cleanup remains an explicit `Effect.addFinalizer((exit) => ...)` call.

### HEM4114

unstable traced operation binding

Hem derives the trace name from the project-relative module path, enclosing named bindings, and operation name. Local bindings may capture dependencies. Colliding names receive a source-location suffix. Mutable, destructured, grouped, wildcard, and anonymous definitions are not supported. Bind the operation with `let operation = effect traced (...) => { ... }` in the appropriate scope.

### HEM4115

promise hidden in effect success

An Effect must own asynchronous execution to supervise, interrupt, time out, retry, and classify its failures. `Effect.succeed(promise)` and `Effect.sync(() => promise)` instead succeed immediately with the Promise as an ordinary value. Use Hem `await` in an effect block or construct the operation with `Effect.tryPromise`.

### HEM4116

duplicate Effect package identities

Effect values, Context tags, Scope, Layers, fibers, and Hem's declaration-origin checks all depend on one coherent runtime identity. Two physical installations remain distinct even when their versions are equal. The diagnostic names a representative incoming import/reexport for each root, or a participating declaration when no such edge is available. Follow those paths to the importing package and repair its dependency graph with the project's package manager and existing lockfile. Keep native TypeScript tests and consumers in the project, then rerun the full check/build/test gate. Do not suppress this check or remove imports merely to hide a second installation.

### HEM4117

generic Effect service has no runtime identity

TypeScript can distinguish `Cache<User>` from `Cache<Order>`, but a generic Context tag cannot: its type arguments do not exist at runtime. Use concrete tags such as `UserCache` and `OrderCache`, or construct tags from explicit runtime keys. Generic methods on a nongeneric service are safe because they do not create competing service identities.

### HEM4118

Effect nested without execution

An Effect placed in another Effect's success or failure channel is ordinary data: the runtime does not execute, supervise, retry, or interrupt it. Hem diagnoses nested carriers at constructors and generator returns. Use postfix `!` to execute the inner Effect, or model an intentional Effect-valued result at an explicit boundary rather than accidentally returning it from an operation.

### HEM4119

for await inside an Effect block

Inside an `effect {}` or `resource {}` block, `await` lifts a single Promise through `Effect.tryPromise`; it does not perform native async iteration. Use `Stream.fromAsyncIterable` with `Stream.runForEach` to iterate a Stream, use `Effect.forEach` over an array, or move the loop into an async helper arrow defined outside the block and lift the helper's Promise with `await`.

## Translated TypeScript diagnostics

TypeScript's own codes, re-rendered in Hem's vocabulary and remapped to authored Hem source. The code is TypeScript's so it stays searchable, but the wording and the reported position are Hem's.

### TS18046

value has unknown type

An `unknown` value is safe to receive but cannot be used until its shape is proven. Narrow it with a type guard, pattern, or checked conversion before accessing members or calling it.

### TS18047

value may be null

A nullable value may be absent. Match or otherwise handle `None` before using the present value.

### TS18048

value may be undefined

An undefined value may be absent. Match or otherwise handle `None` before using the present value.

### TS2304

binding not found

A name must be declared in the current scope or imported from another module before it can be used. JSX punning passes the binding with the same name; write `required={true}` when the intended value is a literal boolean. `type` and `error` are contextual keywords: at the start of a statement `type Name = ...` declares a type alias and `error Name(...)` declares an error, but everywhere else they are ordinary names — an unbound one here is usually a declaration that lost its name, or a `raise` you meant to write. Otherwise add a declaration such as `let value = expression`, import the missing binding, or correct the spelling.

### TS2305

module member not exported

Named imports must match a public export from the target module. Check the module's export list, then change either the export or the name inside `import { name } from "module"`.

### TS2307

module not found

The project must be able to resolve every imported module through its file paths, installed packages, and `tsconfig.json` module-resolution settings. Correct the specifier or make the dependency available to the project.

### TS2322

type mismatch

The value and its destination have different types. Hem shows the smallest incompatible field when TypeScript provides that structure; change the value or the destination annotation so the two types agree.

### TS2339

property not found

Property access must name a member available on the value's current type. Correct the name, narrow a union before accessing variant-specific data, or add the property to the type that owns it.

### TS2345

argument type mismatch

A call argument must be assignable to the corresponding parameter. Change the argument value or choose a function whose parameter accepts that type.

### TS2349

value is not callable

Only values with a call signature can use `value(...)`. Pass a function, select a callable member, or remove the call parentheses.

### TS2351

value is not constructable

The `new` operator requires a value with a construct signature. Use a class or constructor value, or call a factory function without `new`.

### TS2352

cast types do not overlap

Convert the value to the required representation, or narrow it with a checked condition before using it. For example, use `String(value)` to convert a number to text. Hem does not support unchecked assertions: routing a value through `unknown` does not establish its type. Do not move the assertion into TypeScript merely to bypass this refusal; a new unchecked boundary requires explicit human review.

### TS2353

unknown object field

An object literal may provide only fields declared by its expected type. Remove the extra field, correct its name, or extend the destination type when the field belongs there.

### TS2365

operator type mismatch

Binary operators accept specific operand types. Convert one side so both operands fit the operator, or choose an operation defined for the two values you have.

### TS2367

comparison has no overlap

Two types with no possible shared value can never compare equal. Correct the compared value or narrow the surrounding branch so both sides can describe the same value.

### TS2454

binding used before assignment

Every read must follow an assignment on all control-flow paths. Move the read later or ensure each branch assigns the binding before control can reach it.

### TS2540

readonly field write

`let mut` permits rebinding, not field mutation. Create an updated record instead of writing through a readonly reference. If mutation is intended, declare the field `mut` in a record type you own and review its callers; a readonly reference does not grant write permission. These choices can change identity or mutation policy, so Hem offers no automatic fix.

### TS2551

property name misspelled

The value has a property with a nearby spelling. Use the suggested property if it is intended; otherwise narrow or change the value's type before accessing a different member.

### TS2552

binding name misspelled

A nearby in-scope binding has a similar spelling. Use the suggested name if it is the intended value; otherwise import or declare the missing binding explicitly. `type` and `error` are contextual keywords rather than values here, so an unbound one is usually a declaration that lost its name or a `raise` you meant to write; the suggested built-in may also be what you wanted.

### TS2554

wrong argument count

Calls must provide an argument count accepted by the selected signature. Add the missing arguments, remove extras, or call a signature with matching optional and rest parameters.

### TS2561

object field misspelled

An object literal contains a field whose spelling is close to a declared field. Rename it to the suggestion when appropriate, or update the expected type to declare the intended field.

### TS2722

optional function called

An optional function cannot be called until its absence case is handled. Match `Some(fn)` before calling `fn(...)`, or provide a non-optional fallback function.

### TS2741

required field missing

Every required field in the destination type must be present. Add the named field with a compatible value, or make the field optional in the owning type when absence is valid.

### TS2769

no overload matches

An overloaded function publishes several accepted call shapes, and this call matches none of them. Compare the arguments with each signature and change the count or types to fit one complete overload.

### TS7006

parameter type is implicit

Strict projects do not allow an untyped parameter to become `any`. Add a parameter annotation such as `(value: string) => ...`, or supply a contextual function type that determines it.

### TS7053

key cannot index type

Indexed access needs a key known to the target type or an index signature that accepts it. Narrow the key to `keyof Target`, use a declared property, or model the dynamic key space explicitly.

Source: https://hem.run/reference/diagnostics/index.mdx
