kitao/pyxel · error
Failed to parse file '{path}'
Error message
Failed to parse file '{path}' What it means
`parse_tmx` read the file but `serde_xml_rs::from_str::<TmxMap>` failed to deserialize it, returning this error. The XML parse or the structure did not match the expected Tiled TMX schema. The serde error detail is discarded, only the path is reported.
Source
Thrown at crates/pyxel-core/src/tmx_parser.rs:59
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"))?;
let layer = tmx
.layers
.get(layer_index as usize)
.ok_or_else(|| format!("Layer {layer_index} not found in file '{path}'"))?;
if layer.data.encoding != "csv" {View on GitHub (pinned to 50f9bd7778)
Solutions
- Validate the file is well-formed XML (open it in Tiled or an XML validator).
- Confirm the file is a Tiled TMX map, not another format renamed .tmx.
- Re-export the map from Tiled using default/plain settings (no exotic extensions).
- Open the file and check for hand-editing mistakes or truncation; restore from source control.
Example fix
// before
let tilemap = Tilemap::from_tmx("map.json.tmx", 0)?; // actually JSON
// after: export from Tiled as .tmx (XML), then
let tilemap = Tilemap::from_tmx("map.tmx", 0)?; Defensive patterns
Strategy: validation
Validate before calling
// Sanity-check the file looks like TMX XML before parse_tmx
fn looks_like_tmx(path: &str) -> Result<(), String> {
let text = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
if !text.trim_start().starts_with("<?xml") && !text.contains("<map") {
return Err(format!("{} does not look like a Tiled TMX (XML) file", path));
}
Ok(())
} Try / catch
match Tilemap::from_tmx(path, 0) {
Ok(tm) => use_tilemap(tm),
Err(e) if e.starts_with("Failed to parse file") => {
eprintln!("{} is not valid TMX XML; reopen in Tiled and re-save", path);
}
Err(e) => eprintln!("TMX load failed: {}", e),
} Prevention
- Open every map in Tiled at least once before shipping to confirm it parses.
- Do not hand-edit TMX XML without validating afterwards.
- Export maps from Tiled with default settings; avoid experimental format options.
- Store maps in source control so a corrupted file can be restored.
When it happens
Trigger: Calling `parse_tmx(path, layer_index)` on a file that is not valid XML, is an uncompressed/unsupported TMX variant, uses Tiled features not modeled by TmxMap, or is a .tmx exported with a mismatched schema (missing required attributes/elements).
Common situations: Passing a non-XML file (JSON map, image) renamed to .tmx; a corrupted or truncated download; very new Tiled format fields the parser doesn't expect; hand-edited XML with a typo.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to open file '{path}'
- Failed to read 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/acdcf723dcd2a469.
Report an issue: GitHub.