kitao/pyxel · error
Failed to open file '{path}'
Error message
Failed to open file '{path}' What it means
`parse_tmx` failed to open the TMX file at the given path and returns this formatted error string via `Result::Err`. The underlying io::Error is discarded, so only the path is reported. It is the first validation step of loading a Tiled tilemap.
Source
Thrown at crates/pyxel-core/src/tmx_parser.rs:54
#[derive(Debug, Deserialize)]
#[serde(rename = "map")]
struct TmxMap {
#[serde(rename = "@tilewidth")]
tilewidth: u32,
#[serde(rename = "@tileheight")]
tileheight: u32,
#[serde(rename = "tileset", default)]
tilesets: Vec<Tileset>,
#[serde(rename = "layer", default)]
layers: Vec<Layer>,
}
pub fn parse_tmx(path: &str, layer_index: u32) -> Result<RcTilemap, String> {
let err = |msg| format!("{msg} '{path}'");
// Load and validate the TMX layer.
let mut file = File::open(path).map_err(|_| err("Failed to open file"))?;
let mut tmx_text = String::new();
file.read_to_string(&mut tmx_text)
.map_err(|_| err("Failed to read file"))?;
let tmx: TmxMap = serde_xml_rs::from_str(&tmx_text).map_err(|_| err("Failed to parse file"))?;
if tmx.tilewidth != TILE_SIZE || tmx.tileheight != TILE_SIZE {
return Err(err("Invalid tile size in file"));
}
let tileset = tmx
.tilesets
.first()
.ok_or_else(|| err("No tileset found in file"))?;
let columns = tileset
.columns
.ok_or_else(|| err("No embedded tileset in file"))?;
View on GitHub (pinned to 50f9bd7778)
Solutions
- Verify the file exists at the exact path (check spelling and extension).
- Use an absolute path or resolve the path relative to the executable/resources, not the process cwd.
- Check file permissions for the running user.
- Confirm the asset is included in packaged builds (e.g. embedded resources or copied data dir).
Example fix
// before
let tilemap = Tilemap::from_tmx("assets/level.tmx", 0)?;
// after
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/level.tmx");
assert!(path.exists(), "missing TMX: {}", path.display());
let tilemap = Tilemap::from_tmx(path.to_str().unwrap(), 0)?; Defensive patterns
Strategy: validation
Validate before calling
// Check file presence/permissions before calling parse_tmx
fn tmx_readable(path: &str) -> Result<(), String> {
let p = std::path::Path::new(path);
if !p.is_file() {
return Err(format!("TMX file missing: {}", path));
}
std::fs::File::open(p).map(|_| ()).map_err(|e| format!("cannot open {}: {}", path, e))
} Try / catch
match Tilemap::from_tmx(path, 0) {
Ok(tm) => use_tilemap(tm),
Err(e) if e.starts_with("Failed to open file") => {
eprintln!("TMX path bad ({}): check cwd and packaged assets", e);
}
Err(e) => eprintln!("TMX load failed: {}", e),
} Prevention
- Resolve asset paths relative to the executable or embed them at build time, never rely on cwd.
- Ship a startup check that verifies all required .tmx assets exist before the game loop.
- Include data files in packaging/deploy configuration.
- Log the absolute path (canonicalize) when loading fails.
When it happens
Trigger: Calling `parse_tmx(path, layer_index)` (or `Tilemap::from_tmx`) where `File::open(path)` fails: the file does not exist, the path is wrong, permission is denied, or the path is a directory.
Common situations: Typo in the .tmx filename; passing a path relative to the wrong working directory (e.g. binary run from a different cwd); missing data files in a packaged/deployed build; reading a file the user lacks permissions for.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Failed to read file '{path}'
- Failed to parse file '{path}'
- Invalid tile size in file '{path}'
- pyxel.flip is not supported on Pyxel Web
- canvas dimensions are too large
AI-assisted analysis of kitao/pyxel@50f9bd7778 (2026-09-03).
Data as JSON: /api/errors/5e5c91075346e981.
Report an issue: GitHub.