databendlabs/databend · error

Failed to create now_ms function

Error message

Failed to create now_ms function: {}

What it means

A monotonic `metactl.now_ms` clock is registered with mlua's synchronous `create_function`, capturing the setup-time `Instant`. If mlua cannot create the Lua callback wrapper for this closure, the error is wrapped as `Failed to create now_ms function` and environment setup fails.

Solutions

  1. Check the inner mlua error text; treat memory errors by recreating the Lua instance or raising MemoryLimits.
  2. Confirm the closure's captured types (`Instant`) are Send/Sync-compatible with the selected mlua features if the build errors instead.
  3. Re-run in a fresh Lua environment; do not reuse a state that already errored fatally.
  4. Align/upgrade mlua versions workspace-wide if the inner error indicates an mlua regression.
Defensive patterns

Strategy: try-catch

Try / catch

match setup_lua_environment(&lua) {
    Err(e) if e.to_string().contains("Failed to create now_ms function") => {
        // treat as environment setup failure; rebuild Lua state
    }
    other => other?,
}

Prevention

When it happens

Trigger: `lua.create_function(move |_lua, ()| ...)` for `now_ms` failing during `setup_lua_environment` — practically only on Lua allocator/callback-registration failures in the shared runtime.

Common situations: Running metactl Lua scripts in a runtime with exhausted memory or a corrupted Lua state; rarely, an mlua build issue where `create_function` callback slots cannot be allocated.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/638938ca94c8f524. Report an issue: GitHub.

Appendix: source

Thrown at src/meta/control/src/lua_support.rs:470

    let sleep_fn = lua
        .create_async_function(|_lua, seconds: f64| async move {
            let duration = duration_from_seconds(seconds, "sleep")?;
            time::sleep(duration).await;
            Ok(())
        })
        .map_err(|e| anyhow::anyhow!("Failed to create sleep function: {}", e))?;

    metactl_table
        .set("sleep", sleep_fn)
        .map_err(|e| anyhow::anyhow!("Failed to register sleep function: {}", e))?;

    // Register a monotonic millisecond clock for timing and benchmarks. The
    // epoch is this environment's setup time; only differences between calls are
    // meaningful. `Instant` guarantees the value never goes backwards.
    let start = std::time::Instant::now();
    let now_ms_fn = lua
        .create_function(move |_lua, ()| Ok(start.elapsed().as_secs_f64() * 1000.0))
        .map_err(|e| anyhow::anyhow!("Failed to create now_ms function: {}", e))?;

    metactl_table
        .set("now_ms", now_ms_fn)
        .map_err(|e| anyhow::anyhow!("Failed to register now_ms function: {}", e))?;

    // Register the Zipf load generator. The module returns the `ZipfGenerator`
    // table, exposed as `metactl.ZipfGenerator` so any script can call
    // `metactl.ZipfGenerator:new(num_keys, alpha)` directly.
    let zipf_generator = lua
        .load(ZIPF_LOAD_GENERATOR)
        .eval::<Table>()
        .map_err(|e| anyhow::anyhow!("Failed to load zipf_load_generator: {}", e))?;

    metactl_table
        .set("ZipfGenerator", zipf_generator)
        .map_err(|e| anyhow::anyhow!("Failed to register ZipfGenerator: {}", e))?;

    // Set the metactl table as a global

View on GitHub (pinned to 288d84d76e)