{"record":{"id":"dbb0b6817078d638","repo":"BoundaryML/baml","slug":"text-is-required","errorCode":null,"errorMessage":"text is required","messagePattern":"text is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_client_cffi/src/ffi/functions.rs","lineNumber":173,"sourceCode":"    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 text = match kwargs.get(\"text\") {\n        Some(t) => match t.as_str() {\n            Some(s) => s.to_string(),\n            None => {\n                return Err(anyhow::anyhow!(\"text is not a string\"));\n            }\n        },\n        None => {\n            return Err(anyhow::anyhow!(\"text is required\"));\n        }\n    };\n    let allow_stream_types = match kwargs.get(\"stream\") {\n        Some(s) => match s.as_bool() {\n            Some(b) => b,\n            None => {\n                return Err(anyhow::anyhow!(\"stream is not a boolean\"));\n            }\n        },\n        None => false,\n    };\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.\n    let rt = RUNTIME.clone();\n    rt.spawn(async move {\n        let result = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| async {\n            // TODO: There's a race condition bug here. Technically we should COPY the type builder, not just clone it.","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_cffi/src/ffi/functions.rs#L155-L191","documentation":"FFI argument validation for the parse entry point: the kwargs map carried no 'text' entry. The parse function's entire input is the text to parse, so a missing key (empty or malformed argument buffer) is rejected before any parsing runs. A present-but-non-string 'text' is a sibling error ('text is not a string').","triggerScenarios":"Invoking the parse FFI entry point without including the \"text\" key in the kwargs map, e.g. misspelling it as txt or Text.","commonSituations":"Argument name typos, refactors that renamed the variable but not the kwarg key, or calling parse through a generic wrapper that drops unknown kwargs.","solutions":["Pass a \"text\" keyword argument with the string to parse","Check for typos in the argument name (exact lowercase \"text\")","If using a wrapper, ensure it forwards the text argument to the FFI call"],"exampleFix":"// before\nbaml.baml_call_function_parse(rt, \"ExtractResume\")  # no kwargs\n// after\nbaml.baml_call_function_parse(rt, \"ExtractResume\", {\"text\": llm_output})","handlingStrategy":"validation","validationCode":"if \"text\" not in kwargs or kwargs[\"text\"] is None:\n    raise ValueError(\"parse call requires a 'text' kwarg\")","typeGuard":"def has_text(kwargs): return isinstance(kwargs.get('text'), str)","tryCatchPattern":"try:\n    parsed = baml.baml_call_function_parse(rt, fn, kwargs)\nexcept Exception as e:\n    if 'text is required' in str(e):\n        raise ValueError(\"Provide {'text': <llm output string>} to parse\")\n    raise","preventionTips":["Always include the 'text' kwarg (exact spelling) in parse calls","Centralize parse invocations in one helper that validates kwargs","Don't let generic wrappers silently drop unknown kwargs"],"tags":["ffi","rust","missing-argument","parse"],"backgroundTag":"missing-required-argument","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}