sxyazi/yazi · error

The cursor position is out of bounds.

Error message

The cursor position is out of bounds.

What it means

The `shell` action form validates the optional `cursor` field: if set, it must be ≤ the character count of the command string (`run`). A larger value means the caret would sit past the end of the input, so construction bails with this error.

Source

Thrown at yazi-parser/src/mgr/shell.rs:30

	#[serde(default)]
	pub block:       bool,
	#[serde(default)]
	pub orphan:      bool,
	#[serde(default)]
	pub interactive: bool,

	pub cursor: Option<usize>,
}

impl TryFrom<ActionCow> for ShellForm {
	type Error = anyhow::Error;

	fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
		let me: Self = a.deserialize()?;

		if me.cursor.is_some_and(|c| c > me.run.chars().count()) {
			bail!("The cursor position is out of bounds.");
		}

		Ok(me)
	}
}

impl FromLua for ShellForm {
	fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
}

impl IntoLua for ShellForm {
	fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
}

View on GitHub (pinned to 5f901b886b)

Solutions

  1. Clamp cursor to `run.chars().count()` before emitting the action.
  2. Omit cursor (None) to let the shell action default the position.
  3. Compute the cursor with the same char semantics (`chars().count()` / Lua `#` on chars) used by the validator, not byte length.

Example fix

// before
let cursor = Some(old_pos);
ShellForm::from_action(run, cursor)
// after
let n = run.chars().count();
let cursor = Some(old_pos.min(n));
Defensive patterns

Strategy: validation

Validate before calling

assert!(cursor.map_or(true, |c| c <= run.chars().count()),
        "cursor must be <= run.chars().count()");

Type guard

fn is_valid_cursor(run: &str, cursor: Option<usize>) -> bool {
    cursor.map_or(true, |c| c <= run.chars().count())
}

Try / catch

match ShellForm::try_from(action) {
    Ok(form) => open(form),
    Err(e) if e.to_string().contains("cursor position is out of bounds") => {
        eprintln!("cursor beyond end of command: {e}")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Emitting the `mgr:shell` action with a `cursor` value greater than the number of chars in `run` — e.g. `run = "ls"` with `cursor = 5`, or a stale cursor carried over from a longer previous command.

Common situations: Plugin state that remembers the caret position but updates the command to a shorter string; byte-vs-char confusion with multibyte commands (validation counts chars, not bytes); hand-built keymap bindings with hardcoded cursors.

Related errors


AI-assisted analysis of sxyazi/yazi@5f901b886b (2026-09-02). Data as JSON: /api/errors/0471bcde772058d8. Report an issue: GitHub.