windmill-labs/windmill · error
clock is not supported
Error message
clock is not supported
What it means
The windmill-parser-r WASM libc shim stubs clock() (from time.h) with a panic — the WASM sandbox intentionally provides no time source to the compiled C parser. If the tree-sitter C runtime or a custom scanner calls clock() (usually for profiling, timeouts, or debugging instrumentation), the shim panics with "clock is not supported" and the parse fails.
Source
Thrown at backend/parsers/windmill-parser-r/src/wasm_libc.rs:222
}
0 // Return false (0)
}
#[no_mangle]
pub extern "C" fn iswlower(wc: wint_t) -> c_int {
// Check if the character is a lowercase letter ('a' to 'z')
if wc >= 'a' as wint_t && wc <= 'z' as wint_t {
return 1; // Return true (1)
}
0 // Return false (0)
}
// End of AI implemetation
/* --------------------------------- time.h --------------------------------- */
#[no_mangle]
pub unsafe extern "C" fn clock() -> u64 {
panic!("clock is not supported");
}
/* --------------------------------- ctype.h -------------------------------- */
#[no_mangle]
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 {View on GitHub (pinned to e474e8803c)
Solutions
- Rebuild the grammar/scanner without profiling or debug instrumentation (disable TREE_SITTER_DEBUG or equivalent) so clock() is never called.
- Implement clock() in the shim to return a monotonically increasing counter (e.g. a static AtomicU64 of elapsed ticks) instead of panicking, if the value is only used for measurement.
- Patch scanner.c to remove or compile-out the clock() usage for WASM builds (#ifdef TREE_SITTER_WASM).
- Report the grammar upstream so the WASM build drops the timing code.
Example fix
// before (wasm_libc.rs)
#[no_mangle]
pub unsafe extern "C" fn clock() -> u64 {
panic!("clock is not supported");
}
// after — harmless monotonic counter
static CLOCK_TICKS: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
#[no_mangle]
pub unsafe extern "C" fn clock() -> u64 {
CLOCK_TICKS.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot pre-detect the C call, but ensure the grammar build has no profiling:
// at build time, verify the generated C/scanner does not reference clock():
// grep -n '\bclock\s*(' scanner.c src/parser.c # must return nothing for WASM builds Try / catch
try {
return parser.parse(doc);
} catch (e) {
if (String(e).includes('clock is not supported')) {
// rebuild the grammar without profiling/debug instrumentation and retry once
return null; // or trigger the rebuild pipeline
}
throw e;
} Prevention
- Build grammar WASM artifacts with profiling and debug instrumentation disabled.
- Add a build-time check (grep the generated C for clock() references) to CI so a regression fails the build, not the runtime.
- Gate any timing code in scanner.c behind a non-WASM ifdef.
- Test the full parse path in the WASM sandbox after every grammar upgrade.
When it happens
Trigger: The compiled C code calls clock(): a custom scanner.c containing timing/debug instrumentation guarded only by a runtime (not compile-time) flag, or a tree-sitter runtime build with profiling enabled (e.g. TREE_SITTER_DEBUG) that measures parse time via clock().
Common situations: A grammar build that left debug/profiling instrumentation compiled in; a scanner authored for native tree-sitter (where clock() exists) reused in the WASM build; a grammar upgrade that introduced timing code.
Related errors
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/75f70d2960197d9b.
Report an issue: GitHub.