windmill-labs/windmill · error
fputc is not supported
Error message
fputc is not supported
What it means
`fputc` (write a single character to a FILE*) is one of the intentionally unimplemented libc shims in the R parser's WASM runtime: the stub exists only to satisfy linking and panics when entered. Hitting it means executing code that performs character-level stream output the sandbox does not support.
Source
Thrown at backend/parsers/windmill-parser-r/src/wasm_libc.rs:246
pub unsafe extern "C" fn isprint(c: c_int) -> bool {
c >= 32 && c <= 126
}
/* --------------------------------- stdio.h -------------------------------- */
#[no_mangle]
pub unsafe extern "C" fn fprintf(_file: *mut c_void, _format: *const c_void, _args: ...) -> c_int {
panic!("fprintf is not supported");
}
#[no_mangle]
pub unsafe extern "C" fn fputs(_s: *const c_void, _file: *mut c_void) -> c_int {
panic!("fputs is not supported");
}
#[no_mangle]
pub unsafe extern "C" fn fputc(_c: c_int, _file: *mut c_void) -> c_int {
panic!("fputc is not supported");
}
#[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,View on GitHub (pinned to e474e8803c)
Solutions
- Replace the calling code's char-by-char output with a supported mechanism (buffer the string and use a supported path)
- Implement the fputc shim to accumulate/forward output to the host instead of panicking
- Avoid linking the library or code path that depends on stdio character output
- Track as a known unsupported libc symbol if the code cannot be changed
Example fix
// before (stub)
#[no_mangle]
pub unsafe extern "C" fn fputc(_c: c_int, _file: *mut c_void) -> c_int {
panic!("fputc is not supported");
}
// after (forward to host)
#[no_mangle]
pub unsafe extern "C" fn fputc(c: c_int, _file: *mut c_void) -> c_int {
print!("{}", c as u8 as char);
c
} Defensive patterns
Strategy: try-catch
Validate before calling
// Reject R/C sources that emit char-by-char via putc/fputc before execution
if (/\b(fputc|putc)\s*\(/.test(rSource)) {
throw new Error("char-level stdio output (fputc) is unsupported in the R parser WASM");
} Type guard
fn is_unsupported_stdio_symbol(sym: &str) -> bool {
matches!(sym, "fputc" | "putc" | "fputs" | "fwrite" | "fclose" | "fdopen")
} Try / catch
let outcome = std::panic::catch_unwind(AssertUnwindSafe(|| run_wasm_r(payload)));
if let Err(panic) = outcome {
let msg = panic_msg(&panic);
if msg.contains("fputc is not supported") {
// buffer the output path instead: rewrite source to build a string and return it
} else { std::panic::resume_unwind(panic); }
} Prevention
- Build output as complete strings/values instead of incremental character writes
- Inspect dependencies compiled into the WASM for putc/fputc usage
- Catch panics at the WASM boundary and map 'not supported' panics to clear user errors
- Add tests asserting scripts avoid panicking stdio stubs
When it happens
Trigger: Calling the exported `fputc` shim at backend/parsers/windmill-parser-r/src/wasm_libc.rs:246, reached when embedded/compiled code writes characters to stdout/stderr or a file stream.
Common situations: C code compiled into the WASM uses putc/fputc for output loops; a dependency formats output char-by-char; the R parser is run with code that prints incrementally instead of returning a value.
Related errors
- fputs is not supported
- fdopen is not supported
- fclose is not supported
- fwrite is not supported
- vsnprintf is not supported
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/5e20ab955c9686af.
Report an issue: GitHub.