BoundaryML/baml · error

Failed to convert function name to string

Error message

Failed to convert function name to string

What it means

Thrown in call_function_from_c when the C string pointer for the BAML function name cannot be converted to valid UTF-8 Rust String. BAML function names are identifiers, so invalid UTF-8 input from the FFI boundary is rejected before lookup.

Solutions

  1. Ensure the function name is encoded as UTF-8 before passing it through FFI (e.g. s.encode('utf-8') in Python)
  2. Verify the function name matches a function defined in your .baml files
  3. Use the generated client wrapper instead of hand-rolled ctypes calls

Example fix

// before (Python ctypes)
baml.baml_call_function(rt, b"My\xffFunction", ...)
// after
baml.baml_call_function(rt, "MyFunction".encode("utf-8"), ...)
Defensive patterns

Strategy: type-guard

Validate before calling

name = "MyFunction"
assert isinstance(name, str)
name_bytes = name.encode("utf-8")  # raises UnicodeEncodeError early if invalid

Type guard

def is_utf8(s): 
    try: s.encode('utf-8'); return True
    except UnicodeEncodeError: return False

Try / catch

try:
    result = baml.baml_call_function(rt, name_bytes, ...)
except Exception as e:
    if 'Failed to convert function name to string' in str(e):
        raise ValueError(f"Function name must be valid UTF-8: {name!r}")
    raise

Prevention

When it happens

Trigger: Calling baml_call_function (via ctypes/FFI) with a function_name pointer containing non-UTF-8 bytes, or a corrupted/garbage pointer that CStr::from_ptr misinterprets.

Common situations: Manually constructed FFI calls passing bytes instead of encoded strings, wrong struct packing corrupting the char* argument, or passing binary data where a function name is expected.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/6909658102bd244e. Report an issue: GitHub.

Appendix: source

Thrown at engine/language_client_cffi/src/ffi/functions.rs:86

        Err(e) => encode_error_response(e),
    }
}

fn call_function_from_c_inner(
    runtime: *const libc::c_void,
    function_name: *const c_char,
    encoded_args: *const libc::c_char,
    length: usize,
    id: u32,
) -> Result<()> {
    // Safety: assume that the pointers provided are valid.
    let runtime = unsafe { &*(runtime as *const BamlRuntime) };

    // Convert the function name.
    let func_name = match unsafe { CStr::from_ptr(function_name) }.to_str() {
        Ok(s) => s.to_owned(),
        Err(_) => {
            return Err(anyhow::anyhow!("Failed to convert function name to string"));
        }
    };

    // Convert keyword arguments.
    let BamlFunctionArguments {
        kwargs,
        client_registry,
        env_vars,
        collectors,
        type_builder,
        tags,
    } = BamlFunctionArguments::from_c_buffer(encoded_args, length)?;

    let ctx = runtime.create_ctx_manager(BamlValue::String("cffi".to_string()), None);
    let tripwire = trip_wire::make_trip_wire(id);

    // Spawn an async task to await the future and call the callback when done.
    // Ensure that a Tokio runtime is running in your application.

View on GitHub (pinned to bd85ce9dee)