BoundaryML/baml · error · EngineError
Future with ID {future_id} not found
Error message
Future with ID {future_id} not found What it means
`EngineError::FutureNotFound` is raised when a `FutureId` cannot be resolved in the engine's future table. Futures are registered when spawned and removed once resolved or dropped; an unknown ID means it never existed here, was already completed, or was discarded.
Source
Thrown at baml_language/crates/bex_engine/src/lib.rs:804
map.remove(&self.call_id);
let no_active_calls = map.values().all(|call| call.pending);
drop(map);
if no_active_calls {
self.engine.lifecycle_changed.notify_waiters();
}
}
}
/// Errors that can occur during engine execution.
#[derive(Debug, PartialEq, Error, Clone)]
pub enum EngineError {
#[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))]View on GitHub (pinned to bd85ce9dee)
Solutions
- Await each future exactly once and drop the ID afterwards.
- Obtain fresh `FutureId`s from the current engine instance.
- Verify the future was spawned on the same engine being queried.
Example fix
// before let a = engine.future_result(fid).await?; let b = engine.future_result(fid).await?; // second lookup fails // after let a = engine.future_result(fid).await?; // do not reuse fid after completion
Defensive patterns
Strategy: try-catch
Validate before calling
// keep a local registry of pending FutureIds issued by this engine
Try / catch
// rust
match engine.future_result(fid).await {
Err(EngineError::FutureNotFound { .. }) => /* future already resolved or foreign */,
other => other?,
} Prevention
- Await each future exactly once
- Do not reuse FutureIds or share them between engines
- Clear pending-future bookkeeping on shutdown
When it happens
Trigger: Polling, completing, or fetching the result of a future by an ID that the engine has already reaped or never issued.
Common situations: Double-awaiting a future's result; holding future IDs across engine shutdown/restart; ID mixups when multiple engines run concurrently.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- BAML engine is shutting down
- engine is not current with the latest sources; wait for the
- tests have not been collected for this build yet
- Function call with ID {call_id} not found
- Function not found: {name}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/7fc32427480adebe.
Report an issue: GitHub.