sxyazi/yazi · error

Due to Cargo's limitations, Yazi on crates.io must be built

Error message

Due to Cargo's limitations, Yazi on crates.io must be built with `cargo install --force yazi-build`

What it means

Thrown by the impl_into_integer! macro in yazi-shared (yazi-shared/src/data/macros.rs:46) when a Data value is converted to an integer type via TryFrom but its variant is not convertible. Only Data::Integer, Data::Number (whole-valued, in-range floats via float_to_i64), Data::String (parseable), and Data::Id are accepted; any other variant (Bool, Nil, List, Table, Function, etc.) bails with this message. It is the yazi event/plugin bridge's equivalent of a type error: the argument exists but has the wrong shape.

Source

Thrown at yazi-cli/build.rs:14

#[path = "src/args.rs"]
mod args;

use std::{env, error::Error};

use clap::CommandFactory;
use clap_complete::{Shell, generate_to};

fn main() -> Result<(), Box<dyn Error>> {
	let manifest = env::var_os("CARGO_MANIFEST_DIR").unwrap().to_string_lossy().replace(r"\", "/");
	if manifest.contains("/git/checkouts/yazi-")
		|| manifest.contains("/registry/src/index.crates.io-")
	{
		panic!(
			"Due to Cargo's limitations, Yazi on crates.io must be built with `cargo install --force yazi-build`"
		);
	}

	generate()
}

fn generate() -> Result<(), Box<dyn Error>> {
	if env::var_os("YAZI_GEN_COMPLETIONS").is_none() {
		return Ok(());
	}

	let cmd = &mut args::Args::command();
	let bin = "ya";
	let out = "completions";

	std::fs::create_dir_all(out)?;
	for sh in [Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish, Shell::PowerShell] {

View on GitHub (pinned to 441b332de8)

Solutions

  1. Check the Lua call site and pass an actual integer (or a numeric string) for the argument named in the surrounding command
  2. Guard optional values before emitting: only include the argument when it is non-nil
  3. Inspect the delivered Data with ya.dbg()/tracing (YAZI_LOG=debug) to see which variant arrived
  4. If the argument may legitimately be absent, handle it in Rust with get()/str()/bool() defaults or with_opt on the sender side instead of requiring TryFrom

Example fix

-- before
ya.emit("resize", { ratio = true })
-- after
ya.emit("resize", { ratio = 1 })
Defensive patterns

Strategy: validation

Validate before calling

-- Lua: validate before emitting
local function to_int(v)
  local n = tonumber(v)
  assert(n and math.floor(n) == n and math.type(n) == "integer", "expected an integer")
  return n
end
ya.emit("resize", { ratio = to_int(ratio) })

Type guard

-- Lua
local function is_int_like(v)
  local n = tonumber(v)
  return n ~= nil and math.floor(n) == n and n == n
end

Try / catch

-- Lua: catch emit/handler errors
local ok, err = pcall(ya.emit, "resize", { ratio = v })
if not ok then ya.dbg(tostring(err)) end

Prevention

When it happens

Trigger: Calling an event/command handler or plugin API that does `action.get::<u8>(...)` / `take::<usize>(...)` while the Lua side passed a boolean, nil, table, or list for that argument; also strings that fail integer parse produce a different error, but booleans and nil hit exactly this bail. Typical examples: passing `true` instead of `1` for a count/ration, or forgetting an optional argument so nil is delivered.

Common situations: Keymap or plugin config values with wrong types after a yazi upgrade changed an argument's expected type; plugin authors calling ya.emit() with a Lua table where a number is expected; nil leaking through from an unset config option.

Related errors


AI-assisted analysis of sxyazi/yazi@441b332de8 (2026-08-19). Data as JSON: /api/errors/7579f296f3887eb6. Report an issue: GitHub.