windmill-labs/windmill · error

fdopen is not supported

Error message

fdopen is not supported

What it means

fdopen is unimplemented in the Ruby parser WASM libc shim (wasm_libc.rs:251) and panics on call. Opening a file descriptor as a FILE* stream is meaningless inside the WASM sandbox — there is no filesystem — so the symbol is exported purely for link compatibility. Reaching it means the interpreter attempted to open a real I/O stream.

Source

Thrown at backend/parsers/windmill-parser-ruby/src/wasm_libc.rs:251

#[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,
) -> usize {
    panic!("fwrite is not supported");
}

#[no_mangle]

View on GitHub (pinned to e474e8803c)

Solutions

  1. Ensure the parsed code path does not require file I/O — the parser sandbox supports none
  2. Implement fdopen in wasm_libc.rs as a stub returning a null FILE* (letting the caller handle failure) instead of panicking, then rebuild
  3. Upgrade windmill-parser-ruby to a version that handles missing file I/O gracefully
  4. Report the triggering input/backtrace upstream if fdopen should never be reached during parsing

Example fix

// before
pub unsafe extern "C" fn fdopen(_fd: c_int, _mode: *const c_void) -> *mut c_void {
    panic!("fdopen is not supported");
}
// after
pub unsafe extern "C" fn fdopen(_fd: c_int, _mode: *const c_void) -> *mut c_void {
    std::ptr::null_mut() // no filesystem in WASM; signal failure to the caller
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Reject inputs that plausibly require file I/O before parsing:
if (/File\.(open|new)|IO\.open|open\(/.test(rubySource)) {
  console.warn('input references file I/O; parser sandbox has no filesystem');
}

Type guard

function isFdopenPanic(e) {
  return e instanceof Error && e.message.includes('fdopen is not supported');
}

Try / catch

try {
  const ast = rubyParser.parse(rubySource);
} catch (e) {
  if (isFdopenPanic(e)) {
    return { ok: false, reason: 'file-io-unsupported-in-sandbox' };
  }
  throw e;
}

Prevention

When it happens

Trigger: The embedded Ruby parser calls C fdopen to wrap a file descriptor into a FILE*, e.g. when its runtime tries to open or wrap an I/O resource during parsing/initialization.

Common situations: Ruby parser builds whose runtime touches file descriptors; sandboxed/browser WASM with no filesystem host bindings; a dependency change that newly links fdopen.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/52fd06e72d4bf264. Report an issue: GitHub.