# Troubleshooting

Symptom → likely cause → fix. If your app isn't behaving as expected, find the symptom here first.

## Rendering

**The render is blank / empty.**
Likely the app hash isn't registered, or you're calling the wrong render router. Check `ComponentRegistry.exists(hash)`
returns true, and that your deployment's `router` address is correct.

**A data value shows "unavailable."**
The bound resolver reverted, is missing, ran out of gas, or doesn't support the requested kind. This is *fail-closed
working correctly* — the app refused to fabricate a value. Check the resolver address, that it `supportsKind` your
kind, and that its own read isn't reverting.

**A slot always shows its fallback text, even though the resolver and kind are right.**
The `arg` is probably encoded the wrong way. Each kind decodes its args in one exact shape — `abi.encode` of the
listed args, or raw bytes when the kind is marked *packed*. `ensName`, for example, takes exactly the 20 address
bytes; a 32-byte `abi.encode(address)` or a namehash reverts "bad args" and the slot falls back. Check the kind on
**[All Resolver Kinds](../reference/resolver-kinds.md)** and use the SDK encoder where one exists
(`kinds.ens.encodeNameArgs`).

**A role, direction, variant or other setting I wrote isn't in the render.**
`compile()` silently drops a value that isn't in the dictionary (`role: "note"`, `direction: "vertical"`) and any
field it doesn't read — the tree still compiles. Run `checkNode(tree)` (SDK 0.10.0+, or the MCP
`chainrender_check_node` tool): it lists each dropped field with its path. Allowed values are on
**[Node Fields](../reference/node-fields.md)**.

**`u8 out of range: undefined` when compiling.**
A node has a `type` the compiler doesn't have — most often `"heading"`. A heading is `{ "type": "text", "role":
"heading" }` (what `compose.heading()` emits). `checkNode` reports an unknown `type` before you compile.

**A chart renders as axes only (no data).**
The chart's data source is unavailable — same fail-closed behavior. Verify the `IChartData` source resolves.

**The output looks different across RPCs.**
It shouldn't — rendering is deterministic. If output genuinely differs, you're likely rendering *different app
hashes* (e.g. a stale hash on one side) or hitting different router versions. Confirm the same hash + router.

## Grade

**My grade dropped from A to C unexpectedly.**
You introduced a live/off-chain dependency. Read the grade's `breakdown` — it names the exact deviation. Common
causes: an external image (`CLIENT_FETCH`), a mutable dependency, or a fetch without an on-chain fallback. Swap to
an on-chain resolver to return to A.

**The enforcer refused my app.**
Check which rail: over/under-declared capabilities (R2), an action outside the envelope (R3), a value transfer
without `VALUE` (R4), an arbitrary `{to,selector}` (R5), or an unanalyzable token (I5). The rejection message names
it. Declare precisely what you reach; never add an arbitrary-call path. → **[The Capability Enforcer](../concepts/enforcer.md)**

## Theming

**My theme change didn't appear.**
Two cases: (1) if you changed tokens but the deployed app renders an *old seeded theme*, you need to re-seed and
point the app at the new theme id; (2) if you're using the presentation context, confirm you're calling
`renderComponent` with the new `themeId`, not the plain `renderComponent`.

**A spacing/size change had no visible effect.**
The value you changed may be hardcoded rather than token-driven, or you scaled a token that the visible elements
don't reference. Confirm the element uses `var(--cr-*)`. (This exact class of issue is why the token system exists.)

**My theme was rejected at build.**
It failed an invariant — most likely a font below 12px (legibility floor) or a foreground/background pair below
WCAG AA (contrast invariant). Fix the token, don't bypass the check.

## Actions

**The wallet transaction does the wrong thing / nothing.**
Confirm the action declaration (`to`, `sig`, `args`) matches your contract's actual function. `describeAction`
prints the human-readable call — check it says what you expect before signing. `buildActionRequest` constructs
*exactly* the declared call, so a wrong result means a wrong declaration.

## Deployment

**MetaMask says a chunk transaction is "likely to fail".**
After Glamsterdam, storing a large chunk can need more gas than the wallet will send. The visual builder sizes chunks
from the chain's `txGasCap` and measured `storageGas` in `chains.json` (Sepolia: 45,000,000 gas, about 23.6 KB per
chunk) and refuses to send a transaction above the cap. If you still see the warning, the builder you're using
predates that change, or the chain has no `txGasCap` entry. → **[Size Limits & Glamsterdam](../concepts/size-limits-and-glamsterdam.md)**

**A Hardhat script fails with "fields had validation errors".**
Hardhat's local signer refuses any transaction above 30,000,000 gas. Keep the transaction under it, or sign it with
viem directly. → **[Local Build Environment](../guides/local-build-environment.md)**

**`npm audit` reports a high-severity Zod advisory.**
It's GHSA-mrhx-c7xc-m3w5, reached through Hardhat 3's dependency on Zod 3, for which no patch exists. It's dev-only.
Don't run `npm audit fix --force` (it downgrades to Hardhat 2) or override Zod to 4 (it breaks Hardhat's config
validation). → **[Local Build Environment](../guides/local-build-environment.md)**

**My app hash changed and I didn't expect it.**
You changed something baked into identity — text, structure, a role, a declared action, or a baked argument (like a
chart's dimensions or a resolver address in a builder). Presentation (theme/palette) is render-time and doesn't
change the hash; everything else does. → **[Content Addressing](../concepts/content-addressing.md)**

**A viewer/client shows stale behavior after I updated something on-chain.**
The client may be hand-holding a copy of an ABI or address that's now out of date. Ensure your client reads its ABI
and addresses from a single source (the compiled artifact / the addresses file), not a hand-maintained copy — stale
duplicated references are a common integration pitfall.

## Still stuck?

- Re-read the render as *bytes*: decode the actual `renderHash` output and look at what's really there, rather than
  assuming. Most "impossible" render bugs are visible in one look at the real output.
- Check the **[Gotchas, Do's & Don'ts](./gotchas.md)** — your issue may be a known pattern.

## Related
- **[Gotchas, Do's & Don'ts](./gotchas.md)** · **[The Trust Grade](../concepts/trust-grade.md)** ·
  **[The Capability Enforcer](../concepts/enforcer.md)**
