Rust canister backtraces

Is there a way to enable backtraces for panics occuring from within a Rust canister? I have a canister written in Rust that compiles just fine, but it panics somewhere within calling my dependencies, but I have almost no information on the panic: [Canister rrkah-fqaaa-aaaaa-aaaaq-cai] Panicked at 'not supported on this platform', library/std/src/sys/wasm/../unsupported/os.rs:76:5

I would love to get a detailed backtrace on that panic. Any help would be appreciated. I’ve already tried things like export RUST_BACKTRACE=full && dfx start.

4 Likes

I had the same kind of errors (albeit a bit more explicit) when trying to use time, apparently that’s not implemented in wasm.

As for debugging, the old trusty print from time to time helped me along the way:

    ic_cdk::println!("IN");
    [...]
    ic_cdk::println!("OUT");


2 Likes

My code is extremely simple, and unfortunately the panic is somewhere within my dependencies (I’m calling 1 function in the code that panics). A stack trace would probably instantly point out where the issue is, using ic_cdk::println won’t help me because I already know exactly where the problem is in my source code, just not where it’s coming from within the dependency.

Ah, gotcha! That makes sense. Perhaps the dependencies that you include are using libc? I remember a talk by Irina Shestak where she talked about choosing dependencies that either don’t use libc, or that you can configure not to include libc (a.k.a wasm compatible). Check it out, maybe?

Figured it out! I would still like to know how to enable backtraces, but I cloned my dependency (proptest), used some ic_cdk::println statements like you suggested, and tracked it down to some unnecessary OS environment variable configurations. I just commented that code out. So I’ll need to rely on my local version, fork proptest, or do a pull request and see if the environment variables functionality can be feature-gaited or something.

1 Like

Any update? How do I enable stacktraces?
Something divides by 0 and I have no idea where

Stacktraces should get written to canister logs now. dfx canister logs will show you the latest logs

1 Like

Doesn’t seem to be the case, my canister panics and I have absolutely NO IDEA where

2024-12-11 18:47:00.332400685 UTC: [Canister b77ix-eeaaa-aaaaa-qaada-cai] Panicked at 'attempt to divide by zero', /home/dev/.cargo/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.6/src/biguint/division.rs:210:9
2024-12-11 18:47:00.332400685 UTC: [Canister b77ix-eeaaa-aaaaa-qaada-cai] in canister_global_timer: CanisterError: IC0503: Error from Canister b77ix-eeaaa-aaaaa-qaada-cai: Canister called `ic0.trap` with message: Panicked at 'attempt to divide by zero', /home/dev/.cargo/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.6/src/biguint/division.rs:210:9.

this is not a stacktrace, it’s just a place in lib.
Where was it called? How do I debug this?..

1 Like

Is this on the latest dfx version?

dfx --version
dfx 0.24.2

Just updated to 0.24.3, default dfx config nothing fancy

@Severin @let4be

I’m getting the same error, and the debug statement shows it’s because of the dependency used by candid crate: num-bigint, and I’ve changed versions and checked and the error still persists. If there’s any help you can offer to resolve it, please.
PS:
My code isn’t dividing by anything also ( same issue as yours)
dfx version is latest

@Ray04 or @let4be, do you have a link to a repro? I’d like to take a closer look myself

the feature should be available by default, no flags or setup needed.
I just created a simple demo rust project with:

// IMPORTANT: logs are only tracked in replicated mode.
#[ic_cdk::update]
fn div(a: u32, b: u32) -> u32 {
    let c = a / b;
    ic_cdk::print(format!("{} / {} = {}", a, b, c));
    c
}

and called this method 2 times, here’s what I have in the logs:

$ dfx canister logs demo2_backend
[0. 2025-01-07T13:48:29.332070155Z]: 25 / 5 = 5
[1. 2025-01-07T13:48:33.435774182Z]: Panicked at 'attempt to divide by zero', src/demo2_backend/src/lib.rs:10:13
[2. 2025-01-07T13:48:33.435774182Z]: [TRAP]: Panicked at 'attempt to divide by zero', src/demo2_backend/src/lib.rs:10:13
Canister Backtrace:
ic_cdk::api::trap
ic_cdk::printer::set_panic_hook::{{closure}}
std::panicking::rust_panic_with_hook
std::panicking::begin_panic_handler::{{closure}}
std::sys_common::backtrace::__rust_end_short_backtrace
rust_begin_unwind
core::panicking::panic_fmt
core::panicking::panic
demo2_backend::div
ic_cdk::futures::spawn
canister_update div

Is your build process just using the regular dfx build? If you have some additional logic to reduce the wasm size it could be removing the symbols needed to get a backtrace. One way to test is that get wasm-objdump from the wabt repo here and check that you see a name section when inspecting your Wasm:

$ wasm-objdump <your-wasm>

report_backtrace_backend.wasm:  file format wasm 0x1
module name: <report_backtrace_backend.wasm>

Sections:

     Type start=0x0000000b end=0x00000102 (size=0x000000f7) count: 29
   Import start=0x00000104 end=0x0000017e (size=0x0000007a) count: 6
 Function start=0x00000181 end=0x00000475 (size=0x000002f4) count: 754
    Table start=0x00000477 end=0x0000047e (size=0x00000007) count: 1
   Memory start=0x00000480 end=0x00000483 (size=0x00000003) count: 1
   Global start=0x00000485 end=0x0000049e (size=0x00000019) count: 3
   Export start=0x000004a0 end=0x000004e1 (size=0x00000041) count: 4
     Elem start=0x000004e4 end=0x00000732 (size=0x0000024e) count: 1
     Code start=0x00000736 end=0x0005707b (size=0x00056945) count: 754
     Data start=0x0005707f end=0x00061946 (size=0x0000a8c7) count: 1
   Custom start=0x0006194a end=0x000717da (size=0x0000fe90) "name"    <--------------- verify that there is a line like this.
   Custom start=0x000717dc end=0x00071829 (size=0x0000004d) "producers"
   Custom start=0x0007182b end=0x00071874 (size=0x00000049) "target_features"

Also double check that you’re running against a canister that was built with dfx 0.24.3, and that the local network you’re running is using dfx 0.24.3.