{"record":{"id":"44f3842406b553b3","repo":"clockworklabs/SpacetimeDB","slug":"create-bytes-source-bytes-has-length-whic","errorCode":null,"errorMessage":"`create_bytes_source`: `Bytes` has length {}, which is greater than `u32::MAX` {}","messagePattern":"`create_bytes_source`: `Bytes` has length (.+?), which is greater than `u32::MAX` (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/core/src/host/wasmtime/wasm_instance_env.rs","lineNumber":262,"sourceCode":"            .expect(\"allocating next `BytesSink` overflowed `u32`\");\n        id\n    }\n\n    /// Binds `bytes` to the environment and assigns it an ID.\n    ///\n    /// If `bytes` is empty, `BytesSourceId::INVALID` is returned.\n    fn create_bytes_source(&mut self, bytes: bytes::Bytes) -> RtResult<BytesSourceId> {\n        // Pass an invalid source when the bytes were empty.\n        // This allows the module to avoid allocating and make a system call in those cases.\n        if bytes.is_empty() {\n            Ok(BytesSourceId::INVALID)\n        } else if bytes.len() > u32::MAX as usize {\n            // There's no inherent reason we need to error here,\n            // other than that it makes it impossible to report the length in `bytes_source_remaining_length`\n            // and that all of our usage of `BytesSource`s as of writing (pgoldman 2025-09-26)\n            // are to immediately slurp the whole thing into a buffer in guest memory,\n            // which can't hold buffers this big because it's WASM32.\n            Err(anyhow::anyhow!(\n                \"`create_bytes_source`: `Bytes` has length {}, which is greater than `u32::MAX` {}\",\n                bytes.len(),\n                u32::MAX,\n            ))\n        } else {\n            let id = self.alloc_bytes_source_id()?;\n            self.bytes_sources.insert(id, BytesSource { bytes });\n            Ok(id)\n        }\n    }\n\n    pub fn create_extra_bytes_source(&mut self, bytes: bytes::Bytes) -> RtResult<BytesSourceId> {\n        self.create_bytes_source(bytes)\n    }\n\n    fn free_bytes_source(&mut self, id: BytesSourceId) {\n        if self.bytes_sources.remove(&id).is_none() {\n            log::warn!(\"`free_bytes_source` on non-existent source {id:?}\");","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/core/src/host/wasmtime/wasm_instance_env.rs#L244-L280","documentation":"WasmInstanceEnv::create_bytes_source stores a host-side bytes::Bytes buffer for the wasm32 guest to consume via syscalls. The bytes_source_remaining_length syscall reports the length as a u32, so buffers larger than u32::MAX (about 4 GiB) cannot be represented; additionally the guest cannot hold such a buffer in WASM32 memory. The host therefore rejects oversized buffers up front instead of overflowing.","triggerScenarios":"Passing a reducer argument, message, or blob larger than 4 GiB minus 1 into a host call that creates a bytes source (e.g. via create_extra_bytes_source on the instance env).","commonSituations":"Bulk-loading very large binary payloads in a single call; unbounded user-supplied input sizes; tests with synthetic huge buffers.","solutions":["Enforce a maximum payload size at the API boundary and reject oversize inputs with a clear message before they reach the host bridge","Split the payload into chunks below the limit and reassemble in the module or across multiple calls","Store very large blobs out-of-band and pass a reference instead of raw bytes"],"exampleFix":"// before\nlet id = env.create_bytes_source(bytes)?; // bytes.len() > u32::MAX -> error\n\n// after\nconst MAX_BYTES: usize = u32::MAX as usize;\nif bytes.len() > MAX_BYTES {\n    return Err(anyhow::anyhow!(\n        \"payload of {} bytes exceeds the 4 GiB wasm bridge limit; chunk the upload\",\n        bytes.len(),\n    ));\n}\nlet id = env.create_bytes_source(bytes)?;","handlingStrategy":"validation","validationCode":"// Validate payload size before crossing the wasm bridge\nconst MAX_BYTES_SOURCE: usize = u32::MAX as usize;\n\nfn check_bytes_source_size(len: usize) -> Result<(), anyhow::Error> {\n    if len > MAX_BYTES_SOURCE {\n        Err(anyhow::anyhow!(\"payload of {len} bytes exceeds the 4 GiB wasm bridge limit\"))\n    } else {\n        Ok(())\n    }\n}","typeGuard":"fn fits_bytes_source(bytes: &bytes::Bytes) -> bool {\n    !bytes.is_empty() && bytes.len() <= u32::MAX as usize\n}","tryCatchPattern":"match env.create_bytes_source(bytes) {\n    Err(e) if e.to_string().contains(\"greater than `u32::MAX`\") => {\n        // Reject or chunk the upload at the API boundary\n    }\n    other => other,\n}","preventionTips":["Cap request/reducer payload sizes well below 4 GiB at the edge","Chunk large uploads and reassemble in the module","Add fuzz/soak tests with oversize buffers to confirm clean rejection"],"tags":["spacetimedb","wasm","wasmtime","bytes-source","payload-size"],"backgroundTag":"payload-too-large","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}