tursodatabase/turso · error · napi::Error
{message}: {e}
Error message
{message}: {e} What it means
Generic napi error formatter in the JS binding: to_error(status, message, e) renders any Rust std::error::Error as "{message}: {e}" under a caller-chosen napi status. Unlike to_generic_error it is used where the call site picks a specific status; the message prefix still identifies which binding operation failed.
Source
Thrown at bindings/javascript/src/lib.rs:233
// make the JS step loop spin without letting the backoff expire.
let sleep_ms = duration.as_millis().clamp(1, u32::MAX as u128) as u32;
Ok((STEP_SLEEP, sleep_ms))
}
Ok(turso_core::StepResult::Done) => Ok((STEP_DONE, 0)),
Ok(turso_core::StepResult::Interrupt) => {
Err(create_generic_error("statement was interrupted"))
}
Ok(turso_core::StepResult::Busy) => Err(create_generic_error("database is locked")),
Err(e) => Err(to_generic_error("step failed", e)),
}
}
fn to_generic_error<E: std::error::Error>(message: &str, e: E) -> napi::Error {
Error::new(Status::GenericFailure, format!("{message}: {e}"))
}
fn to_error<E: std::error::Error>(status: napi::Status, message: &str, e: E) -> napi::Error {
Error::new(status, format!("{message}: {e}"))
}
fn create_generic_error(message: &str) -> napi::Error {
Error::new(Status::GenericFailure, message)
}
fn create_error(status: napi::Status, message: &str) -> napi::Error {
Error::new(status, message)
}
fn query_timeout_duration(timeout_ms: u32) -> Option<std::time::Duration> {
if timeout_ms > 0 {
Some(std::time::Duration::from_millis(timeout_ms as u64))
} else {
None
}
}
View on GitHub (pinned to 244cde92a7)
Solutions
- Identify the failing operation from the prefix before the first colon, then treat the suffix as the authoritative native error string
- Check the JS arguments passed to that exact API (types, required options)
- For open/prepare failures, validate the database path and SQL text before calling
- Upgrade the JS and native halves of the binding together
Defensive patterns
Strategy: try-catch
Type guard
function isBindingWrapperError(e: unknown): e is Error {
return e instanceof Error && e.message.includes(': ');
} Try / catch
try { db.open(); } catch (e) { const msg = String((e as Error).message); const op = msg.slice(0, msg.indexOf(': ')); const cause = msg.slice(msg.indexOf(': ') + 2); console.error(`${op} failed: ${cause}`); } Prevention
- Validate option objects before passing them to binding APIs
- Treat the suffix after the first colon as the authoritative native error
- Log full messages - the prefix names the binding call to fix
When it happens
Trigger: Any napi entry point that maps a native error with a non-generic status - argument conversion or open/prepare failures inside the JS wrapper - producing messages like "<operation>: <Rust error string>".
Common situations: Passing wrong argument types or option shapes from JS, opening a database at an unusable path, or wrapper/engine version drift; the operation named before the colon is the API that failed.
Related errors
- GenericFailure
- GenericFailure
- Only finite numbers (not Infinity or NaN) can be passed as a
- BigInt value is outside SQLite's signed 64-bit integer range
- BigInt value is outside SQLite's signed 64-bit integer range
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/39a9955da4c1b10b.
Report an issue: GitHub.