{"record":{"id":"25192f6e93a14775","repo":"windmill-labs/windmill","slug":"fprintf-is-not-supported-25192f","errorCode":null,"errorMessage":"fprintf is not supported","messagePattern":"fprintf is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-r/src/wasm_libc.rs","lineNumber":236,"sourceCode":"/* --------------------------------- time.h --------------------------------- */\n\n#[no_mangle]\npub unsafe extern \"C\" fn clock() -> u64 {\n    panic!(\"clock is not supported\");\n}\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]","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-r/src/wasm_libc.rs#L218-L254","documentation":"The windmill-parser-r WASM libc shim stubs fprintf (stdio.h) with a panic, because the WASM sandbox has no file descriptors or output streams for the compiled C parser to write to. Any code path that tries to print (error messages, debug logging, scanner diagnostics via fprintf(stderr, ...)) hits this stub and panics with \"fprintf is not supported\".","triggerScenarios":"The compiled tree-sitter C runtime or custom scanner calls fprintf — typically fprintf(stderr, ...) in an error/debug path: logging an unexpected token, a scanner error branch, or debug instrumentation left compiled in.","commonSituations":"Parsing R input that reaches a scanner error branch containing fprintf(stderr, ...); a grammar built with debug logging enabled; a grammar upgrade whose error handling now prints; reusing a native-targeted scanner that assumes stderr exists.","solutions":["Trace which call site invokes fprintf (instrument the shim to log the format string and then panic) and fix the input/state that reaches that error branch.","Reimplement fprintf in the shim to format and route output to console.log via the existing console_log! macro instead of panicking, so error paths degrade to log output.","Rebuild the grammar without debug instrumentation (disable debug flags) so fprintf is compiled out.","Patch the grammar's scanner.c to remove or gate fprintf usage for WASM builds."],"exampleFix":"// before (wasm_libc.rs)\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// after — route output to the console instead of panicking\n#[no_mangle]\npub unsafe extern \"C\" fn fprintf(_file: *mut c_void, _format: *const c_void, _args: ...) -> c_int {\n    let msg = cstr(_format); // read the NUL-terminated format string\n    console_log!(\"fprintf: {}\", msg);\n    msg.len() as c_int\n}","handlingStrategy":"try-catch","validationCode":"// At build time, confirm the compiled parser does not call fprintf:\n//   grep -n 'fprintf' scanner.c src/parser.c  # should be absent or WASM-gated\n// At runtime, validate input before parsing to avoid error branches:\nfunction validateDoc(src) {\n  return typeof src === 'string' && src.length > 0 && !src.includes('\\u0000');\n}","typeGuard":"function isCleanStringDoc(src) {\n  return typeof src === 'string' && src.length > 0 && !src.includes('\\u0000');\n}","tryCatchPattern":"try {\n  if (!validateDoc(doc)) throw new TypeError('invalid parser input');\n  return parser.parse(doc);\n} catch (e) {\n  if (String(e).includes('fprintf is not supported')) {\n    // scanner hit an error/log branch using stdio: recreate parser,\n    // inspect the document, and route it to a manual-review queue\n    parser = new Parser();\n    return null;\n  }\n  throw e;\n}","preventionTips":["Rebuild grammars without debug logging so fprintf is compiled out of WASM artifacts.","Add a CI check that the generated C contains no fprintf references for WASM builds.","Reimplement stdio stubs to log to console instead of panicking, so error paths degrade gracefully.","Isolate each parse in a fresh parser instance; a panicking stub can leave shared state corrupted for later parses."],"tags":["wasm","libc","stdio","tree-sitter","unsupported-function"],"backgroundTag":"wasm-libc-stub-panic","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"}