windmill-labs/windmill · error

vsnprintf is not supported

Error message

vsnprintf is not supported

What it means

The `vsnprintf` stub panics: formatted string rendering with varargs is not implemented in the WASM libc shim. Even though vsnprintf writes to a memory buffer (not a stream), the library chose not to implement printf-family formatting, so the symbol is link-compat only and any call is fatal.

Source

Thrown at backend/parsers/windmill-parser-java/src/wasm_libc.rs:190

#[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, ... );
#[no_mangle]
pub extern "C" fn snprintf() {
    panic!("snprintf is not supported");
}

#[no_mangle]
pub extern "C" fn __assert_fail(_: *const i32, _: *const i32, _: *const i32, _: *const i32) {
    panic!("oh no");
}

View on GitHub (pinned to e474e8803c)

Solutions

  1. Replace vsnprintf usage in the compiled component with the Rust-side format!/format_args! (the shim already uses it) or a simple string builder.
  2. Upgrade windmill-parser-java in case newer builds provide a vsnprintf implementation.
  3. Avoid the formatted-message code path by changing the parsed input.
  4. If the call site is a third-party dependency, propose or vendor a minimal vsnprintf implementation for the shim.

Example fix

// before
vsnprintf(buf, sizeof(buf), "count=%d", ap);

// after: build the string without printf family
console_log!("count={}", count); // uses format_args! under the hood
Defensive patterns

Strategy: try-catch

Validate before calling

if (!input || typeof input !== 'string') throw new Error('invalid parser input');

Try / catch

try {
  const result = parse(input);
} catch (e) {
  if (String(e).includes('vsnprintf is not supported')) {
    throw new Error('native component used printf-family formatting; unsupported in parser WASM');
  }
  throw e;
}

Prevention

When it happens

Trigger: Code inside the WASM module calls `vsnprintf(buf, size, fmt, args)` — building formatted messages, log lines, or error strings via the printf family (often through wrappers like log_printf or error-formatters).

Common situations: Native components formatting diagnostics or error messages; sprintf-style helpers implemented on top of vsnprintf; string-building utilities in bundled C code.

Related errors


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