BoundaryML/baml · error · EngineError

Function `{name}` is not invokable as an entry point (kind:

Error message

Function `{name}` is not invokable as an entry point (kind: {kind})

What it means

`EngineError::NotInvokableAsEntry` is raised when a function exists but its `FunctionKind` cannot serve as an engine entry point. Only bytecode functions may be invoked via `BexEngine::call_function` / `call_function_bound_args`; native (`$rust_function`) entries would re-enter the VM through `YieldToCall` with no bytecode frame to return to, and sysops/builtins are reached from inside a calling bytecode body.

Source

Thrown at baml_language/crates/bex_engine/src/lib.rs:816

    #[error("BAML engine is shutting down")]
    ShuttingDown,

    #[error("Function call with ID {call_id} not found")]
    FunctionCallNotFound { call_id: CallId },

    #[error("Future with ID {future_id} not found")]
    FutureNotFound { future_id: FutureId },

    #[error("Function not found: {name}")]
    FunctionNotFound { name: String },

    /// Function exists, but its `FunctionKind` is not invokable as an
    /// engine entry point. Only bytecode functions can be called via
    /// [`BexEngine::call_function`] / [`BexEngine::call_function_bound_args`]:
    /// native (`$rust_function`) entries would re-enter the VM through
    /// `YieldToCall` with no bytecode frame to return to. Sysops + builtins
    /// reach their natives from inside a calling bytecode body.
    #[error("Function `{name}` is not invokable as an entry point (kind: {kind})")]
    NotInvokableAsEntry { name: String, kind: String },

    #[error("VM internal error: {0}")]
    VmInternalError(bex_vm::errors::VmInternalError),

    #[error("{}", format_vm_internal_error(source, trace))]
    TracedVmInternalError {
        source: bex_vm::errors::VmInternalError,
        trace: Vec<bex_vm::StackFrame>,
    },

    /// Either a BAML panic or a BAML error value.
    #[error("{}", format_unhandled_throw(value, trace))]
    UnhandledThrow {
        value: Box<BexExternalValue>,
        trace: Vec<bex_vm::StackFrame>,
    },

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Invoke a bytecode (BAML-defined) function instead; have it call the native internally.
  2. Call native/builtin functionality through its direct Rust API rather than the engine entry point.
  3. Check the function's `FunctionKind` before invoking if constructing names dynamically.

Example fix

// before
engine.call_function("$rust_function_concat", args).await?;
// after
engine.call_function("MyBamlWorkflow", args).await?; // bytecode fn that calls the native
Defensive patterns

Strategy: validation

Validate before calling

// rust
let f = engine.lookup_function(name)?;
if f.kind() != FunctionKind::Bytecode { /* route elsewhere */ }

Type guard

fn is_bytecode_entry(kind: &FunctionKind) -> bool { matches!(kind, FunctionKind::Bytecode) }

Prevention

When it happens

Trigger: Passing the name of a native function, sysop, or builtin to `call_function` / `call_function_bound_args`; the kind is embedded in the error message.

Common situations: Trying to call a Rust-implemented builtin directly from the host; scripting against internal engine primitives as if they were BAML functions.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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