windmill-labs/windmill · error

Aborted from C

Error message

Aborted from C

What it means

The windmill-parser-r WASM module provides abort() as a libc shim that panics with "Aborted from C". When the C code compiled into the parser (tree-sitter runtime or scanner) calls abort(), the panic converts the C abort into a Rust panic that terminates the parse. This is a deliberate translation: the WASM sandbox has no real libc, so abort cannot actually terminate a process.

Source

Thrown at backend/parsers/windmill-parser-r/src/wasm_libc.rs:15

use std::collections::BTreeMap;
use std::sync::{Mutex, OnceLock};
use std::{
    alloc::{self, Layout},
    ffi::{c_char, c_int, c_void},
    mem::align_of,
    ptr,
};
use wasm_bindgen::prelude::*;

/* -------------------------------- stdlib.h -------------------------------- */

#[no_mangle]
pub unsafe extern "C" fn abort() {
    panic!("Aborted from C");
}

macro_rules! console_log {
    ($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string()) })
}

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(a: &str);
}

#[no_mangle]
pub unsafe extern "C" fn malloc(size: usize) -> *mut c_void {
    if size == 0 {
        return ptr::null_mut();
    }

View on GitHub (pinned to e474e8803c)

Solutions

  1. Identify which C call site invokes abort() by building the parser with debug symbols or instrumenting the shim to log a wasm backtrace before panicking.
  2. Validate/normalize the R input being parsed; try a minimal snippet to find the construct that trips the abort.
  3. Check for an earlier panic in the same parse (fprintf/snprintf/clock stubs) that left state inconsistent — fix that root cause.
  4. Align the tree-sitter runtime and grammar versions so scanner and runtime ABIs match.

Example fix

// before (wasm_libc.rs)
#[no_mangle]
pub unsafe extern "C" fn abort() {
    panic!("Aborted from C");
}

// after — log a backtrace before panicking to find the C call site
#[no_mangle]
pub unsafe extern "C" fn abort() {
    console_log!("abort() called from C");
    panic!("Aborted from C");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard the entry point and isolate each parse:
function prepareDoc(src) {
  if (typeof src !== 'string' || src.length === 0) {
    throw new TypeError('expected non-empty string document');
  }
  return src;
}

Type guard

function isNonEmptyString(v) {
  return typeof v === 'string' && v.length > 0;
}

Try / catch

try {
  const tree = parser.parse(prepareDoc(src));
  return tree;
} catch (e) {
  if (String(e).includes('Aborted from C')) {
    // C-level abort: recreate the parser and treat this document as unparseable
    parser = new Parser();
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Any C code path in the R parser that calls abort(): failed internal invariant checks in the tree-sitter C runtime, custom scanner error handling that gives up, or an assertion path that funnels into abort() instead of __assert_fail.

Common situations: Parsing pathological or very large R input that drives the grammar into an unexpected state; a scanner version mismatch with the tree-sitter runtime ABI; memory corruption earlier in the parse (e.g. from an incomplete shim such as a panicking fprintf/snprintf) that later triggers abort.

Related errors


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