{"record":{"id":"a8502f0b9096335b","repo":"windmill-labs/windmill","slug":"fputs-is-not-supported-a8502f","errorCode":null,"errorMessage":"fputs is not supported","messagePattern":"fputs is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-ruby/src/wasm_libc.rs","lineNumber":241,"sourceCode":"}\n\n/* --------------------------------- ctype.h -------------------------------- */\n\n#[no_mangle]\npub unsafe extern \"C\" fn isprint(c: c_int) -> bool {\n    c >= 32 && c <= 126\n}\n\n/* --------------------------------- stdio.h -------------------------------- */\n\n#[no_mangle]\npub unsafe extern \"C\" fn fprintf(_file: *mut c_void, _format: *const c_void, _args: ...) -> c_int {\n    panic!(\"fprintf is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fputs(_s: *const c_void, _file: *mut c_void) -> c_int {\n    panic!(\"fputs is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fputc(_c: c_int, _file: *mut c_void) -> c_int {\n    panic!(\"fputc is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fdopen(_fd: c_int, _mode: *const c_void) -> *mut c_void {\n    panic!(\"fdopen is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fclose(_file: *mut c_void) -> c_int {\n    panic!(\"fclose is not supported\");\n}\n\n#[no_mangle]","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-ruby/src/wasm_libc.rs#L223-L259","documentation":"fputs is a stub that panics in the Ruby parser WASM libc shim (wasm_libc.rs:241). The WASM guest has no stdout/stderr streams, so string output via C fputs is unsupported; the symbol is exported only so the compiled Ruby parser links. Reaching it means the interpreter attempted to write a string to a stream.","triggerScenarios":"The embedded Ruby parser calls C fputs — typically printing diagnostics, warnings, or output from the interpreter while processing Ruby source.","commonSituations":"Ruby code that triggers interpreter warnings; parser builds wired to print errors via fputs; sandboxed runtimes lacking stdio host functions.","solutions":["Implement fputs in wasm_libc.rs to forward the string to the console_log helper and rebuild","Suppress interpreter output (warning/verbose flags of the embedded Ruby) so fputs is never reached","Upgrade to a parser build that routes output instead of panicking","Adjust the Ruby input to avoid provoking interpreter output"],"exampleFix":"// before\npub unsafe extern \"C\" fn fputs(_s: *const c_void, _file: *mut c_void) -> c_int {\n    panic!(\"fputs is not supported\");\n}\n// after\npub unsafe extern \"C\" fn fputs(s: *const c_void, _file: *mut c_void) -> c_int {\n    console_log!(\"{}\", c_str_to_rust(s));\n    0\n}","handlingStrategy":"try-catch","validationCode":"// Smoke-test the parser with a small input before production use:\nawait rubyParser.parse('1'); // panics with fputs if the build links output paths","typeGuard":"function isFputsPanic(e) {\n  return e instanceof Error && e.message.includes('fputs is not supported');\n}","tryCatchPattern":"try {\n  const ast = rubyParser.parse(rubySource);\n} catch (e) {\n  if (isFputsPanic(e)) return null;\n  throw e;\n}","preventionTips":["Implement fputs to forward strings to console_log when rebuilding the parser","Suppress interpreter output channels (verbose/warning flags) in the host runtime","Never assume partial parse results — the panic discards the whole run","Re-validate your Ruby corpus after each parser WASM upgrade"],"tags":["wasm","rust","libc","stdio","ruby"],"backgroundTag":"wasm-libc-function-not-supported","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}