QuipNetwork/hashsigs-rs · error · Error
{err.message}
Error message
{err.message} What it means
This is a wasm-binding boundary error: any WasmErr produced inside the Rust library is converted into a JavaScript js_sys::Error whose message text is the underlying err.message. The library throws it so Rust-side failures (parsing, validation, internal errors) surface as native JS Error objects when the wasm API is called from JavaScript. A machine-readable `code` property is also attached to the Error via Reflect::set.
Solutions
- Read error.code from the caught Error object to get the machine-readable error code, not just message.
- If code is absent, parse the leading `[CODE] ` prefix from error.message (the fallback format used when Reflect::set fails).
- Validate inputs in JS before calling the wasm API so WasmErr is never produced.
- Check instanceof Error and the library's documented code values to branch on failure kinds.
Example fix
// before
catch (e) {
console.log(e.message); // loses machine-readable code
}
// after
catch (e) {
const code = e.code ?? (/^\[(.+?)\] /.exec(e.message)?.[1]);
console.log(code, e.message);
} Defensive patterns
Strategy: try-catch
Validate before calling
function assertValidPublicKey(s) {
if (typeof s !== 'string' || !/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(s)) {
throw new TypeError('invalid publicKey argument');
}
} Type guard
function isWasmError(e) {
return e instanceof Error && (typeof e.code === 'string' || /^\[.+?\] /.test(e.message));
} Try / catch
try {
wasmApi(input);
} catch (e) {
if (isWasmError(e)) {
const code = e.code ?? /^\[(.+?)\] /.exec(e.message)?.[1];
handleWasmFailure(code, e.message);
} else {
throw e;
}
} Prevention
- Validate arguments (formats, lengths, encodings) in JS before crossing the wasm boundary.
- Always read error.code, not just message, when handling failures from this library.
- Handle both message shapes: plain message and the `[CODE] message` fallback.
- Keep the wasm bindings and JS wrapper versions in sync with documented error codes.
When it happens
Trigger: Calling any wasm-exported API (compiled with the `wasm-bindings` feature) that internally returns a WasmErr; js_error() is invoked and creates the JS Error with the original err.message as its message and err.code as a `code` property.
Common situations: JS/TypeScript callers passing malformed input (bad publicKey, invalid serialized data) into wasm functions; callers reading only error.message and losing the `code` field because they don't know it's a custom property; environments where Reflect::set silently fails and the code is folded into the message as `[CODE] message` instead.
Related errors
AI-assisted analysis of QuipNetwork/hashsigs-rs@128c4ccb5c (2026-09-08).
Data as JSON: /api/errors/2aef699df06d774c.
Report an issue: GitHub.
Appendix: source
Thrown at src/wasm/mod.rs:1680
stateful_policy: stateful_policy_name(account.statefulPolicy()),
next_stateful_leaf_index: account.nextStatefulLeafIndex(),
recovery_mode: account.recoveryMode(),
}
}
#[cfg(any(test, feature = "wasm-bindings"))]
fn hex_string(bytes: &[u8]) -> String {
let mut out = String::from("0x");
for byte in bytes {
use core::fmt::Write;
let _ = write!(out, "{byte:02x}");
}
out
}
#[cfg(feature = "wasm-bindings")]
fn js_error(err: WasmErr) -> JsValue {
let e = js_sys::Error::new(&err.message);
if js_sys::Reflect::set(&e, &JsValue::from_str("code"), &JsValue::from_str(err.code)).is_err() {
// Reflect::set failed, so the machine-readable code would be lost off the
// Error object. Fold it into the message so callers never lose it.
return js_sys::Error::new(&format!("[{}] {}", err.code, err.message)).into();
}
e.into()
}
/// Build a serde-boundary error handler tagged with a STATIC argument label
/// (e.g. `"publicKey"`). The label identifies which argument failed to
/// deserialize without ever echoing the caller-supplied value (inputs include
/// secret seeds). Returns a closure so call sites read
/// `.map_err(js_error_from_serde("publicKey"))`.
#[cfg(feature = "wasm-bindings")]
fn js_error_from_serde(label: &'static str) -> impl Fn(serde_wasm_bindgen::Error) -> JsValue {
move |_error| {
js_error(WasmErr {
code: ERR_INVALID_INPUT,View on GitHub (pinned to 128c4ccb5c)