sxyazi/yazi · error

Process failed

Error message

Process failed

What it means

yazi-scheduler's background process runner (`bg`) waits on the spawned child process and, after logging its exit status, checks `status.success()`. A non-zero exit code (or signal termination) makes the task fail with the generic message "Process failed" — the real exit code is available in the preceding ProcessOutBg::Log output.

Solutions

  1. Check the task log output for "Exited with status code: N" to see the real code
  2. Run the same command manually in a shell to reproduce and fix the underlying failure
  3. Fix the command's arguments, PATH, or working directory in the task definition
  4. If terminated by signal, investigate why (signal value in the log, dmesg for OOM)

Example fix

// before
shell("rsync -wrongflag src dst")
// after
shell("rsync -av src dst") // verify flags with `rsync --help` first
Defensive patterns

Strategy: try-catch

Try / catch

match task_result {
    Err(e) if e.to_string() == "Process failed" => {
        eprintln!("bg task exited non-zero; check ProcessOutBg::Log for the status code");
    }
    other => other,
}

Prevention

When it happens

Trigger: Any shell command dispatched as a background task exits non-zero (e.g. `ExitStatus(code)`), or is killed by a signal (`status.code() == None`).

Common situations: User-defined plugin/shell tasks where the command has a bug or bad arguments; commands missing a dependency on the target system; OOM-killer or user Ctrl-C terminating the process by signal.

Related errors


AI-assisted analysis of sxyazi/yazi@a541adde4e (2026-09-02). Data as JSON: /api/errors/76f46dc11db2abd7. Report an issue: GitHub.

Appendix: source

Thrown at yazi-scheduler/src/process/process.rs:79

		let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines();
		let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines();
		loop {
			select! {
				Ok(Some(line)) = stdout.next_line() => {
					self.ops.out(id, ProcessOutBg::Log(line));
				}
				Ok(Some(line)) = stderr.next_line() => {
					self.ops.out(id, ProcessOutBg::Log(line));
				}
				status = child.wait() => {
					let status = status.map_err(anyhow::Error::from)?;
					self.ops.out(id, ProcessOutBg::Log(match status.code() {
						Some(code) => format!("Exited with status code: {code}"),
						None => "Process terminated by signal".to_string(),
					}));
					if !status.success() {
						Err(anyhow!("Process failed"))?;
					}
					break;
				}
			}
		}

		Ok(self.ops.out(id, ProcessOutBg::Succ))
	}
}

impl Process {
	#[inline]
	pub(crate) fn submit(&self, r#in: impl Into<ProcessIn>, priority: u8) {
		_ = self.tx.try_send(r#in.into(), priority);
	}
}

View on GitHub (pinned to a541adde4e)