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

  1. Validate the file is well-formed XML (open it in Tiled or an XML validator).
  2. Confirm the file is a Tiled TMX map, not another format renamed .tmx.
  3. Re-export the map from Tiled using default/plain settings (no exotic extensions).
  4. 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

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

Related errors


AI-assisted analysis of kitao/pyxel@50f9bd7778 (2026-09-03). Data as JSON: /api/errors/acdcf723dcd2a469. Report an issue: GitHub.