# Troubleshooting

> Every way a guest stops short of a verified proof, by symptom. Exit statuses, fatal executor errors, refused ELFs, refused programs, failed proofs and verifier errors, with the cause and the fix.

A guest can stop short of a verified proof at six points. Find the symptom, then the row.

## The run exits with a status you did not expect

The run finished and is provable; the guest chose to fail. The SDK's own statuses:

| Status | Cause | What to do |
| --- | --- | --- |
| 70 | `commit` would pass 16,380 bytes | Commit a digest of the output instead of the output |
| 71 | an allocation would end above `__stack_top − 8 MiB` or above the live `sp` | Nothing is freed, so the run's *total* allocation must fit between the image and `0x7F80_0000`. Reuse buffers across loops and size them with `with_capacity` ([the heap](https://apogee.gweb3networks.com/docs/launch/write#heap)) |
| 72 | a delegation answered what its shim refuses: an error, or `-ENOSYS` after a multi-call operation's first call | Use the SDK's functions rather than raw frames, and keep operands below their modulus |
| 101 | a panic, which prints nothing | Run the same inputs through the host build of your library, where the panic message prints ([test on the host](https://apogee.gweb3networks.com/docs/launch/write#host-first)) |

Any other status is your own `exit(code)`.

## The run stops with a fatal error

The emulator returns an `EmuError` and there is no exit status and no proof:

| Error | Usual cause |
| --- | --- |
| `OutOfBounds` | a null or wild pointer (`[0, 0x8000)` is a hole), an advice read past what the host supplied, `advice()` on a run with no advice, or a delegation frame not wholly in RAM |
| `Misaligned` | a halfword or word access through an unaligned pointer, or a misaligned delegation frame |
| `NotAnInstruction` | a jump to a pc holding no instruction, including the all-zero `c.unimp` halfword |
| `IllegalInstruction` | an encoding the machine does not execute |
| `Ebreak` | an `ebreak`, which has no proof |
| `ClockOverflow` | more than `2^36 − 1` cycles |
| `PublicInputTooLong`, `JournalTooLong` | an input, or the journal's length word at exit, above 16,380 bytes |
| `DelegationFrame` | a frame its circuit has no witness for: a `MOD_MUL` or `EC_ADD` operand at or above its modulus, a selector naming nothing, a keccak round above 23, a SHA-256 group above 15, a Poseidon2 lane at or above `p` |
| `DelegationFamilyAbsent` | a delegation number the image never declared, on a tracing path |

## The ELF is refused

`artifact-dump`, `host::setup` and the tools refuse an ELF the loader cannot take, with a `LoaderError`:

| Refusal | Usual cause |
| --- | --- |
| `NotAnElf`, `Truncated` | not the guest's ELF: a `.d` file, a partial write |
| `NotRiscV`, `UnsupportedElfType`, `RelocatableElf`, `DynamicElf` | a host build, an object file, a PIE or a dynamically linked build |
| `BadSegment`, `NoExecutableSegment`, `EntryNotAnInstruction` | an edited `link.ld`, or no `_start` linked |
| `RvcIllegal`, `InstructionTooLong`, `TextTruncated` | data in `.text`, such as a table in hand-written assembly. Never the zero halfword, which is expected |

## The program does not register

The ELF loads but the program cannot be decoded into a configuration:

| Refusal | Cause and fix |
| --- | --- |
| `Not all opcodes supported: pc=…` | a word outside RV32IMA anywhere in executable code, reachable or not, such as a CSR access or `fence.i` in assembly. Remove it |
| `TableTooShort` | code past a family's table reach. Raise that family's height: `2^22` reaches 7.9375 MiB of code |
| `ProgramTooLarge` | the image is past `bytecode_size_words`, 4 MiB by default. Raise the ceiling in `ProgramParams` |
| `ImageOutsideWindow` | a file-backed byte lies past RAM window 0 at your window height. Raise the window height |
| `HeightNotOnMenu` | a height that is not `2^8`, `2^12`, `2^16`, `2^18`, `2^20` or `2^22` |
| `UnknownDelegation` | the image declares a delegation number no family answers |

A key also fails to build if a family the program uses is set below its floor, `2^20` for an instruction family and `2^16` for the RAM window families, since no circuit exists there.

## The prover fails

An honest prover proving what the emulator executed does not fail, so a failure points at an input it should not have accepted or at a bug. Two cases account for most:

- **A call with no proof.** A system call outside `EXIT` and the delegations, which a library made for host data, answers `-ENOSYS` and the run continues, but the prover's fill refuses that row and names the cycle. Find the dependency that asks for randomness or time.
- **Out of memory.** The process is killed while shards are in flight. Lower the third argument of `host::prove`, or lower heights.

For anything else, rebuild with the prover's debug log and rerun:

```sh
cargo run --release -p bench --features prover/debug-info -- prove ...
APOGEE_DEBUG=detail <the run> 2>&1 | tee run.log
grep -c 'begin h=' run.log; grep -c 'gkr done' run.log     # unequal: a shard died
grep 'begin h=' run.log | tail -1                           # which one
grep -E 'FAIL|NOT CANONICAL|UNBALANCED|OVER the|NAMES NO|DISAGREES|NOT LOOPING|ABORTED' run.log
```

`self_check FAILED` names the row's first failing gate and every operand's value. [The debug log](https://apogee.gweb3networks.com/docs/reference/tools#s3) lists every marker.

## Verification fails

`verify_shard` and `verify_block` return a `VerifyError` whose class says what broke:

| Class | Meaning |
| --- | --- |
| `Statement` | the statement does not fit the key: shard counts, window rules, payload lengths, lists, or the global digest the proof was seeded with |
| `Malformed` | the proof's shape is not its circuit's: counts of commitments, outputs, rounds or claims |
| `Constraint { layer }` | a gate is violated, or a layer's sumcheck fails |
| `Lookup { channel }` | a looked-up tuple is in no row of its table |
| `MemoryArgument` | the read and write multisets do not reconcile, or a public window does not hold the statement's bytes |
| `Opening` | a commitment opening fails |

If you built the proof with Apogee's own prover from an execution the emulator accepted, a verification failure means the verifier and the prover disagree about the program: check that you load the key the proof was made under, at the same heights, over the same ceremony.

## Identity mismatch

The identity you computed differs from the one you expected:

- **Another machine's build.** The ELF embeds absolute paths, so a rebuild elsewhere is another image. Compare against the ELF that was proved, not a fresh build.
- **Other heights.** Every height is bound into the identity. `artifact-dump tables` reports the identity at the default heights; your setup may use others.
- **Another ceremony.** A Hermez powers-of-tau file is a different `τ`, so every commitment differs. Check the file's `[τ]_1` against [the ceremony's](https://apogee.gweb3networks.com/docs/launch/setup#ceremony).
