Troubleshooting

Insufficient Memory or Stack Size

Jolt provides reasonable defaults for the total allocated memory and stack size. It is however possible that the defaults are not sufficient, leading to unpredictable errors within our tracer. To fix this we can try to increase these sizes. We suggest starting with the stack size first as this is much more likely to run out.

Below is an example of manually specifying both the total memory and stack size.


#![allow(unused)]
#![cfg_attr(feature = "guest", no_std)]
#![no_main]

fn main() {
extern crate alloc;
use alloc::vec::Vec;

#[jolt::provable(stack_size = 10000, heap_size = 10000000)]
fn waste_memory(size: u32, n: u32) {
    let mut v = Vec::new();
    for i in 0..size {
        v.push(i);
    }
}
}

Maximum Input or Output Size Exceeded

Jolt restricts the size of the inputs and outputs to 4096 bytes by default. Using inputs and outputs that exceed this size will lead to errors. These values can be configured via the macro.


#![allow(unused)]
#![cfg_attr(feature = "guest", no_std)]
#![no_main]

fn main() {
#[jolt::provable(max_input_size = 10000, max_output_size = 10000)]
fn sum(input: &[u8]) -> u32 {
    let mut sum = 0;
    for value in input {
        sum += *value as u32;
    }

    sum
}
}

Guest Attempts to Compile Standard Library

Sometimes after installing the toolchain the guest still tries to compile with the standard library which will fail with a large number of errors that certain items such as Result are referenced and not available. This generally happens when one tries to run jolt before installing the toolchain. To address, try rerunning jolt install-toolchain, restarting your terminal, and delete both your rust target directory and any files under /tmp that begin with jolt.

Guest Fails to Compile on the Host

By default, Jolt will attempt to compile the guest for the host architecture. This is useful if you want to run and test the guest's tagged functions directly. If you know your guest code cannot compile on the host (for example, if your guest uses inline RISCV assembly), you can specify to only build for the guest architecture.


#![allow(unused)]
fn main() {
#[jolt::provable(guest_only)]
fn inline_asm() -> (i32, u32, i32, u32) {
    use core::arch::asm;

    let mut data: [u8; 8] = [0; 8];
    unsafe {
        let ptr = data.as_mut_ptr();

        // Store Byte (SB instruction)
        asm!(
        "sb {value}, 0({ptr})",
        ptr = in(reg) ptr,
        value = in(reg) 0x12,
        );
    }
}
}

Null Pointer Write / "Unknown memory mapping: 0x0"

If you see Null pointer write detected (store to 0x0) or Illegal device store: Unknown memory mapping: 0x0, it means your guest program crashed. This happens when musl's abort() cannot deliver a signal and falls back to writing to a null pointer.

The most common cause is a missing jolt-sdk feature. If your guest uses:

  • rayon or threading — add "thread" to your jolt-sdk features
  • randomness (getrandom) — add "random" to your jolt-sdk features
[dependencies]
jolt = { package = "jolt-sdk", features = ["guest-std", "thread", "random"] }

To diagnose which syscall is failing, add the "debug" feature to enable syscall logging:

jolt = { package = "jolt-sdk", features = ["guest-std", "debug"] }

This prints every syscall the guest makes (e.g. [syscall] SYS_clone), which helps identify which capability is missing.

Release runs with fat LTO fail a lookup-table test

If cargo nextest run --release -p jolt-core fails at:

'zkvm::lookup_table::equal::test::prefix_suffix' panicked at jolt-core/src/zkvm/lookup_table/test.rs:108:17:
assertion `left == right` failed

this appears to be a fat LTO miscompile in the current compiler pass pipeline. This class of miscompilations is generally tracked in rust-lang/rust#116941.

Workarounds

  • Prefer thin LTO (default in Cargo.toml):
    • profile.release.lto = "thin"
  • If you must keep fat LTO, disable LLVM prepopulate passes (use Cargo’s profile override to avoid applying LTO to proc-macro/build scripts):
    • CARGO_PROFILE_RELEASE_LTO=fat RUSTFLAGS="-C no-prepopulate-passes"

These avoid the miscompile while keeping release runs functional.

LTO Configuration Details

We have investigated three primary LTO configurations.

1. lto = "fat" (Problematic)

Enabling "fat" LTO without additional flags triggers a compiler miscompilation in the current toolchain.

To reproduce:

CARGO_PROFILE_RELEASE_LTO=fat cargo nextest run --release -p jolt-core -E 'test(=zkvm::lookup_table::equal::test::prefix_suffix)'

You will see an error similar to:

thread 'zkvm::lookup_table::equal::test::prefix_suffix' panicked at jolt-core/src/zkvm/lookup_table/test.rs:108:17:
assertion `left == right` failed
  left: 3421757210433941145757981284077922153733430471292915370254709621273756639318
 right: 15993602859885613318374216934674599210221976492830069114166327961258944178919

The above error can be fixed by setting lto = "thin". You can verify with:

CARGO_PROFILE_RELEASE_LTO=thin cargo nextest run --release -p jolt-core -E 'test(=zkvm::lookup_table::equal::test::prefix_suffix)'

3. lto = "fat" with -C no-prepopulate-passes

If you must use fat LTO, adding RUSTFLAGS="-C no-prepopulate-passes" prevents the miscompilation described above. However, this flag alters the guest ELF code generation, which can increase the execution trace length slightly.

This may cause tests with tight trace length limits—such as advice_e2e_dory—to fail.

To reproduce:

CARGO_PROFILE_RELEASE_LTO=fat RUSTFLAGS="-C no-prepopulate-passes" cargo nextest run --release -p jolt-core -E 'test(=zkvm::prover::tests::advice_e2e_dory)'

You will see a trace length error:

    thread 'zkvm::prover::tests::advice_e2e_dory' panicked at jolt-core/src/zkvm/prover.rs:336:13:
    Execution trace length (105501 cycles, padded to 131072) exceeds max_trace_length (65536) configured in MemoryConfig. Increase max_trace_length to at least 131072.

To fix this, simply increase the max_trace_length in the failing test setup. For example, in advice_e2e_dory:

let shared_preprocessing = JoltSharedPreprocessing::new(
    bytecode.clone(),
    io_device.memory_layout.clone(),
    init_memory_state,
-   1 << 16,
+   1 << 17,
);

Getting Help

If none of the above solve the problem, please create a Github issue with a detailed bug report including the Jolt commit hash, the hardware or container configuration used, and a minimal guest program to reproduce the bug.