windmill-labs/windmill · error
fwrite is not supported
Error message
fwrite is not supported
What it means
The WASM Ruby parser stubs libc `fwrite` with an unconditional panic because writing to C stdio streams is impossible in the sandbox. Any Ruby VM or parsed code path that writes to a FILE* stream aborts with this message. It is a deliberate guard against unsupported libc surface.
Source
Thrown at backend/parsers/windmill-parser-ruby/src/wasm_libc.rs:266
#[no_mangle]
pub unsafe extern "C" fn fdopen(_fd: c_int, _mode: *const c_void) -> *mut c_void {
panic!("fdopen is not supported");
}
#[no_mangle]
pub unsafe extern "C" fn fclose(_file: *mut c_void) -> c_int {
panic!("fclose is not supported");
}
#[no_mangle]
pub unsafe extern "C" fn fwrite(
_ptr: *const c_void,
_size: usize,
_nmemb: usize,
_stream: *mut c_void,
) -> usize {
panic!("fwrite is not supported");
}
#[no_mangle]
pub unsafe extern "C" fn vsnprintf(
_buf: *mut c_char,
_size: usize,
_format: *const c_char,
_args: ...
) -> c_int {
panic!("vsnprintf is not supported");
}
#[no_mangle]
pub extern "C" fn clock_gettime(ptr: usize, new_size: usize) {
panic!("clock_gettime is not supported");
}
// int snprintf( char* restrict buffer, size_t bufsz, const char* restrict format, ... );View on GitHub (pinned to e474e8803c)
Solutions
- Remove stream writes from the Ruby code under parse; return values instead of writing them out
- Use in-memory constructs (strings, arrays) rather than IO objects
- Implement a WASI-backed fwrite shim if output streaming is a real requirement
Example fix
// before
File.open('out.txt', 'w') { |f| f.write(data) }
// after
return data # let the host handle persistence Defensive patterns
Strategy: validation
Validate before calling
fn writes_to_streams(ruby_src: &str) -> bool {
["File.open", "IO.write", "f.write", ".puts", ".print"]
.iter().any(|p| ruby_src.contains(p))
} Try / catch
match std::panic::catch_unwind(|| parse_ruby(source)) {
Ok(res) => res,
Err(e) => { log::warn!("ruby parser: stream write attempted in sandbox"); Err(format_parser_error(e)) }
} Prevention
- Have scripts return data instead of writing it to files/streams
- Reject scripts using IO write APIs during submission
- Keep parser-facing gems pure-Ruby where possible
When it happens
Trigger: Calling the exported `fwrite` symbol, or Ruby code whose execution path performs buffered stream writes (puts/print to a stdio FILE*, gem internals using fwrite).
Common situations: Ruby script prints to a file handle or a gem writes via stdio during parsing; no real stream exists in wasm so the stub fires.
Related errors
- fclose is not supported
- vsnprintf is not supported
- clock_gettime is not supported
- snprintf is not supported
- clock is not supported
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/2f71bf8d0f9cef97.
Report an issue: GitHub.