BoundaryML/baml · error

text is not a string

Error message

text is not a string

What it means

call_function_parse_from_c requires a keyword argument named "text" that must be a BAML string value, because it invokes the special parse operation on raw text. If "text" is present but is not a string (e.g. an int, bool, or object), the library raises this error instead of coercing.

Source

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

        }
    };

    // 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 text = match kwargs.get("text") {
        Some(t) => match t.as_str() {
            Some(s) => s.to_string(),
            None => {
                return Err(anyhow::anyhow!("text is not a string"));
            }
        },
        None => {
            return Err(anyhow::anyhow!("text is required"));
        }
    };
    let allow_stream_types = match kwargs.get("stream") {
        Some(s) => match s.as_bool() {
            Some(b) => b,
            None => {
                return Err(anyhow::anyhow!("stream is not a boolean"));
            }
        },
        None => false,
    };

    // 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)

Solutions

  1. Coerce the value to a string before calling parse (str(text) / String(text))
  2. Verify you are using the parse API correctly — it expects the raw LLM output string
  3. Log the type of the value passed as text to confirm what the host actually sends

Example fix

// before
baml.baml_call_function_parse(rt, "fn", {"text": 12345})
// after
baml.baml_call_function_parse(rt, "fn", {"text": str(llm_output)})
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(text, str):
    raise TypeError(f"text must be str, got {type(text)}")

Type guard

def is_str(v): return isinstance(v, str)

Try / catch

try:
    parsed = baml.baml_call_function_parse(rt, fn, {"text": text})
except Exception as e:
    if 'text is not a string' in str(e):
        parsed = baml.baml_call_function_parse(rt, fn, {"text": str(text)})
    else:
        raise

Prevention

When it happens

Trigger: Calling the parse FFI entry point with kwargs containing text as a non-string BamlValue (int, list, bool, etc.).

Common situations: Passing user input or parsed data directly as text without str() conversion; mixing up the parse API's argument contract with generic function calls.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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