sxyazi/yazi · error · anyhow::Error

Unknown copy type: {}

Error message

Unknown copy type: {}

What it means

Raised by Action::take (yazi-shared/src/event/action.rs:180) when a consuming lookup by DataKey finds nothing in the args map. take() removes the entry (move-out semantics), so beyond a missing argument it also fails on double consumption: a second take of the same name or index after the first one removed it. Every form's TryFrom<ActionCow> is built on take/take_any, so this error surfaces when the incoming action lacks a required argument or was already drained.

Source

Thrown at yazi-actor/src/mgr/copy.rs:54

					s.extend_from_slice(&form.separator.transform(&f.url.to_strand()));
				}
				"dirpath" | "dirname" => {
					if let Some(p) = f.content_path().parent() {
						s.extend_from_slice(&form.separator.transform(&p));
					}
				}
				"dirurl" => {
					if let Some(p) = f.url.parent() {
						s.extend_from_slice(&form.separator.transform(&p.to_strand()));
					}
				}
				"filename" => {
					s.extend_from_slice(&form.separator.transform(&f.name().unwrap_or_default()));
				}
				"name_without_ext" => {
					s.extend_from_slice(&form.separator.transform(&f.stem().unwrap_or_default()));
				}
				_ => bail!("Unknown copy type: {}", form.r#type),
			};
			if it.peek().is_some() {
				s.push(b'\n');
			}
		}

		// Copy the CWD path regardless even if the directory is empty
		if s.is_empty() && matches!(&*form.r#type, "dirpath" | "dirname") {
			s.extend_from_slice(&form.separator.transform(&cx.current().content_path()));
		} else if s.is_empty() && form.r#type == "dirurl" {
			s.extend_from_slice(&form.separator.transform(&cx.cwd().to_strand()));
		}

		futures::executor::block_on(CLIPBOARD.set(s));
		succ!();
	}
}

View on GitHub (pinned to 441b332de8)

Solutions

  1. Ensure the emitter attaches the argument with the exact key (with/with_any in Rust, matching table key in Lua) before dispatch
  2. Make sure only one consumer takes a given argument; use get()/any() for read-only inspection and leave take() to the single owner
  3. Verify positional order — take(0) is the first positional, take(1) the second; a missing earlier arg shifts everything
  4. Trace with YAZI_LOG=debug to see the action's args at dispatch time

Example fix

// before
let id: u64 = a.take("id")?; // sender never attached "id"
// after
let action = action.with("id", 42u64);
// ... then dispatch; form's take("id") succeeds
Defensive patterns

Strategy: validation

Validate before calling

// Rust: attach every argument a form will take
let action = Action::new_relay("tasks:output")?.with("id", id).with_any("out", out);

Try / catch

// Rust: single-owner consumption
match form::Output::try_from(action) { Ok(f) => ..., Err(e) => tracing::warn!("bad action: {e:#}") }

Prevention

When it happens

Trigger: A form's TryFrom calling a.take("name")/take_first()/take_second() for an argument the sender never attached; two forms (or a form plus a plugin hook) consuming the same positional argument from one ActionCow; argument name mismatch between emitter and receiver; positional index shift after an earlier argument was omitted.

Common situations: Plugin or keymap emitting a command without a required parameter after a yazi version renamed it; internal command re-dispatch paths that try to read an argument already taken by an earlier handler; copy-pasted form code reading the wrong key name.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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