clockworklabs/SpacetimeDB · error
{errno}
Error message
{errno} What it means
Panic in the safe wrapper over the procedure_http_request syscall. Request-level failures (DNS, connect, timeout) are deliberately mapped by the host to HTTP_ERROR, which the wrapper returns as Err(BytesSource) - those do not panic. The panic fires only for the remaining errnos: WOULD_BLOCK_TRANSACTION (a transaction is currently open) and BSATN_DECODE_ERROR (the serialized spacetimedb_lib::http::Request was malformed).
Source
Thrown at crates/bindings-sys/src/lib.rs:1655
) -> Result<(raw::BytesSource, raw::BytesSource), raw::BytesSource> {
let mut out = [raw::BytesSource::INVALID; 2];
let res = unsafe {
super::raw::procedure_http_request(
http_request_bsatn.as_ptr(),
http_request_bsatn.len() as u32,
body.as_ptr(),
body.len() as u32,
&mut out as *mut [raw::BytesSource; 2],
)
};
match super::Errno::from_code(res) {
// Success: `out` is a `spacetimedb_lib::http::Response`.
None => Ok((out[0], out[1])),
// HTTP_ERROR: `out` is a `spacetimedb_lib::http::Error`.
Some(errno) if errno == super::Errno::HTTP_ERROR => Err(out[0]),
Some(errno) => panic!("{errno}"),
}
}
}
View on GitHub (pinned to 6dee26c6ef)
Solutions
- Move outbound HTTP calls out of reducers - perform them from an HTTP-module handler context where no reducer transaction is open.
- Handle the Err return path (HTTP_ERROR) for real request failures instead of assuming success.
- Align the spacetimedb crate version with the host version and republish the module.
Example fix
// before: outbound HTTP from a reducer (transaction open -> panic)
#[spacetimedb::reducer]
fn call_api(ctx: &ReducerContext) {
let _ = spacetimedb::http::client::request(req).unwrap(); // panics WOULD_BLOCK_TRANSACTION
}
// after: outbound HTTP in an http handler; reducers only enqueue work
#[spacetimedb::http]
fn trigger_api() { let _ = spacetimedb::http::client::request(req); } Defensive patterns
Strategy: validation
Try / catch
match spacetimedb::http::client::request(req) {
Ok(resp) => { /* http::Response */ }
Err(err_source) => { /* read http::Error from the BytesSource - real request failure */ }
} Prevention
- Never issue outbound HTTP requests from reducers - a transaction is always open there.
- Route external calls through module HTTP handlers and have reducers record work items instead.
- Always handle the Err variant; HTTP-level failures are data, not panics.
When it happens
Trigger: Issuing an outbound HTTP request from inside a reducer - reducers always hold an open transaction, so the host returns WOULD_BLOCK_TRANSACTION; or a Request whose BSATN encoding fails to decode because the module's spacetimedb lib version is out of sync with the host.
Common situations: Trying to validate input by calling an external API from a reducer; moving outbound calls into module HTTP handlers without checking which context they run in; crate/host version skew after an upgrade.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Error getting jwt: {errno}
- cannot serialize refs without a typespace
- cannot deserialize refs without a typespace
- unexpected error from `_row_iter_bsatn_advance`: {e}
- Cannot nest router at `{path}`; existing routes overlap with
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/fa8f8d59e3d8eb23.
Report an issue: GitHub.