windmill-labs/windmill · error
fputc is not supported
Error message
fputc is not supported
What it means
fputc is stubbed to panic in the Ruby parser WASM libc shim (wasm_libc.rs:246). Single-character output via C fputc cannot work in the sandbox (no real streams), so the shim only exists to satisfy linking of the compiled Ruby parser. A panic here means the interpreter tried to emit one character to a FILE*.
Source
Thrown at backend/parsers/windmill-parser-ruby/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
- Implement fputc to buffer/forward characters to console_log in wasm_libc.rs and rebuild the WASM
- Disable or redirect the interpreter's output paths (verbose/warning configuration) so fputc is not called
- Upgrade windmill-parser-ruby to a build that no longer panics on fputc
- Modify the Ruby input that makes the parser emit output
Example fix
// before
pub unsafe extern "C" fn fputc(_c: c_int, _file: *mut c_void) -> c_int {
panic!("fputc is not supported");
}
// after
pub unsafe extern "C" fn fputc(c: c_int, _file: *mut c_void) -> c_int {
console_log!("{}", (c as u8) as char);
c
} Defensive patterns
Strategy: try-catch
Validate before calling
// No cheap pre-check exists; validate input shape to reduce diagnostic paths:
if (typeof rubySource !== 'string' || rubySource.length === 0) {
throw new TypeError('rubySource must be a non-empty string');
} Type guard
function isFputcPanic(e) {
return e instanceof Error && e.message.includes('fputc is not supported');
} Try / catch
try {
const ast = rubyParser.parse(rubySource);
} catch (e) {
if (isFputcPanic(e)) {
console.warn('Ruby parser tried char-level output; skipping input');
return null;
}
throw e;
} Prevention
- Buffer fputc output in the shim and forward to console_log on rebuild
- Disable guest output paths that write character-by-character
- Track which inputs trigger interpreter printing and exclude them from the parser
- Pin parser builds tested against your corpus
When it happens
Trigger: The embedded Ruby parser calls C fputc — commonly from low-level character output routines in error printing or stream writing during parsing.
Common situations: Interpreter diagnostics built on character-at-a-time output; parser builds whose printf machinery falls back to fputc; WASM environments without stdio host imports.
Related errors
- fprintf is not supported
- fputs is not supported
- snprintf is not supported
- clock is not supported
- fdopen is not supported
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/5795ec17e04ab60d.
Report an issue: GitHub.