Affected: template pinned to ankurah 0.9.0 (rn-bindings/Cargo.toml).
rn-bindings/src/init.rs init_runtime() builds a multi-thread tokio runtime and enters it on the calling thread, but never registers the handle with ankurah:
pub fn init_runtime() {
let rt = RUNTIME.get_or_init(|| {
Builder::new_multi_thread().enable_all().build().unwrap()
});
// missing: ankurah::set_runtime_handle(rt.handle().clone());
ENTER_GUARD.with(|g| { /* … rt.enter() … */ });
}
rt.enter() only sets the ambient runtime for the current thread. ankurah's task::spawn (ankurah-core task.rs) tries Handle::try_current() and, on a thread with no ambient tokio context, falls back to the handle registered via set_runtime_handle() — panicking if none was ever set:
RUNTIME_HANDLE
.get()
.expect("task::spawn: no Tokio runtime context on this thread. Call ankurah::set_runtime_handle() at init time.")
The #[uniffi::export] async fn init_node future is driven by the uniffi/RN foreign async executor, not by this tokio runtime, so ankurah's internal spawns (durable system load/readiness, storage I/O) run on threads where Handle::try_current() fails. With no registered fallback handle the spawn panics; the panic unwinds across the FFI boundary and surfaces to JS as an opaque error (observed: a null where a String was expected), and node bring-up fails at startup. The offline/durable path (init_node(None)) is the clearest repro.
Fix: register the handle right after building the runtime:
ankurah::set_runtime_handle(rt.handle().clone());
A host #[tokio::main] process has an ambient runtime, which is why the pure-Rust examples work without this — the omission only bites the FFI host.
Affected: template pinned to ankurah 0.9.0 (
rn-bindings/Cargo.toml).rn-bindings/src/init.rsinit_runtime()builds a multi-thread tokio runtime and enters it on the calling thread, but never registers the handle with ankurah:rt.enter()only sets the ambient runtime for the current thread. ankurah'stask::spawn(ankurah-coretask.rs) triesHandle::try_current()and, on a thread with no ambient tokio context, falls back to the handle registered viaset_runtime_handle()— panicking if none was ever set:The
#[uniffi::export] async fn init_nodefuture is driven by the uniffi/RN foreign async executor, not by this tokio runtime, so ankurah's internal spawns (durable system load/readiness, storage I/O) run on threads whereHandle::try_current()fails. With no registered fallback handle the spawn panics; the panic unwinds across the FFI boundary and surfaces to JS as an opaque error (observed: a null where a String was expected), and node bring-up fails at startup. The offline/durable path (init_node(None)) is the clearest repro.Fix: register the handle right after building the runtime:
A host
#[tokio::main]process has an ambient runtime, which is why the pure-Rust examples work without this — the omission only bites the FFI host.