sxyazi/yazi · error · anyhow::Error
not a File
Error message
not a File
What it means
Data is yazi's dynamic typed value used at Lua/action boundaries. File::try_from(Data) unwraps the contained value with into_any::<File>(); if the Data holds any other type (string, table, different struct), the conversion fails with "not a File". It is a type mismatch at a dynamically-typed boundary, not a filesystem error.
Source
Thrown at yazi-fs/src/file/data.rs:13
use anyhow::{anyhow, bail};
use yazi_macro::impl_data_any;
use yazi_shared::data::Data;
use crate::file::{File, Files};
impl_data_any!(File, from_into_lua = inherit);
impl TryFrom<Data> for File {
type Error = anyhow::Error;
fn try_from(value: Data) -> Result<Self, Self::Error> {
value.into_any::<Self>().ok_or_else(|| anyhow!("not a File"))
}
}
impl TryFrom<&Data> for File {
type Error = anyhow::Error;
fn try_from(value: &Data) -> Result<Self, Self::Error> {
value.as_any::<Self>().cloned().ok_or_else(|| anyhow!("not a File"))
}
}
impl TryFrom<Data> for Files {
type Error = anyhow::Error;
fn try_from(value: Data) -> Result<Self, Self::Error> {
let Data::List(files) = value else { bail!("not a list of Files") };
files.into_iter().map(File::try_from).collect::<Result<_, _>>().map(Self)
}View on GitHub (pinned to 94abcfa92f)
Solutions
- Pass the actual File value through (e.g. from a Folder's entries) instead of re-wrapping other data
- Branch on the contained type before converting (as_any::<File>()) and give a precise error
- On the Lua side, keep File userdata intact rather than converting to tables
Example fix
// before
let f = File::try_from(data)?; // data actually holds a Strand
// after
let Some(f) = data.into_any::<File>() else {
bail!("expected a File, got a different type");
}; Defensive patterns
Strategy: type-guard
Validate before calling
// Check the contained type before consuming: ensure!(data.as_any::<File>().is_some(), "expected a File"); let f = File::try_from(data)?;
Type guard
fn is_file(d: &Data) -> bool { d.as_any::<File>().is_some() } Try / catch
match data.into_any::<File>() {
Some(f) => f,
None => bail!("expected a File, got a different Data type"),
} Prevention
- Narrow with as_any before converting at dynamic boundaries
- Keep File values flowing as File, not re-wrapped in other Data
- Validate types at the Lua boundary where everything is dynamic
When it happens
Trigger: Passing a Data wrapping something else where a File is required: extracting plugin/action arguments, decoding event payloads, or feeding results of generic Data-valued APIs into File::try_from.
Common situations: Lua-side code handing untyped values into Rust helpers; payload shape drift after type changes; plugins re-wrapping File fields into plain tables.
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/0d5fbf6c274d6288.
Report an issue: GitHub.