{"record":{"id":"6909658102bd244e","repo":"BoundaryML/baml","slug":"failed-to-convert-function-name-to-string","errorCode":null,"errorMessage":"Failed to convert function name to string","messagePattern":"Failed to convert function name to string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_client_cffi/src/ffi/functions.rs","lineNumber":86,"sourceCode":"        Err(e) => encode_error_response(e),\n    }\n}\n\nfn call_function_from_c_inner(\n    runtime: *const libc::c_void,\n    function_name: *const c_char,\n    encoded_args: *const libc::c_char,\n    length: usize,\n    id: u32,\n) -> Result<()> {\n    // Safety: assume that the pointers provided are valid.\n    let runtime = unsafe { &*(runtime as *const BamlRuntime) };\n\n    // Convert the function name.\n    let func_name = match unsafe { CStr::from_ptr(function_name) }.to_str() {\n        Ok(s) => s.to_owned(),\n        Err(_) => {\n            return Err(anyhow::anyhow!(\"Failed to convert function name to string\"));\n        }\n    };\n\n    // Convert keyword arguments.\n    let BamlFunctionArguments {\n        kwargs,\n        client_registry,\n        env_vars,\n        collectors,\n        type_builder,\n        tags,\n    } = BamlFunctionArguments::from_c_buffer(encoded_args, length)?;\n\n    let ctx = runtime.create_ctx_manager(BamlValue::String(\"cffi\".to_string()), None);\n    let tripwire = trip_wire::make_trip_wire(id);\n\n    // Spawn an async task to await the future and call the callback when done.\n    // Ensure that a Tokio runtime is running in your application.","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_cffi/src/ffi/functions.rs#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the function name is encoded as UTF-8 before passing it through FFI (e.g. s.encode('utf-8') in Python)","Verify the function name matches a function defined in your .baml files","Use the generated client wrapper instead of hand-rolled ctypes calls"],"exampleFix":"// before (Python ctypes)\nbaml.baml_call_function(rt, b\"My\\xffFunction\", ...)\n// after\nbaml.baml_call_function(rt, \"MyFunction\".encode(\"utf-8\"), ...)","handlingStrategy":"type-guard","validationCode":"name = \"MyFunction\"\nassert isinstance(name, str)\nname_bytes = name.encode(\"utf-8\")  # raises UnicodeEncodeError early if invalid","typeGuard":"def is_utf8(s): \n    try: s.encode('utf-8'); return True\n    except UnicodeEncodeError: return False","tryCatchPattern":"try:\n    result = baml.baml_call_function(rt, name_bytes, ...)\nexcept Exception as e:\n    if 'Failed to convert function name to string' in str(e):\n        raise ValueError(f\"Function name must be valid UTF-8: {name!r}\")\n    raise","preventionTips":["Always encode names with .encode('utf-8')","Use the generated client wrappers instead of raw ctypes","Never pass bytes read from binary sources as function names"],"tags":["ffi","rust","encoding","utf-8"],"backgroundTag":"invalid-argument-format","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}