{"record":{"id":"109d35ab94971307","repo":"a-b-street/abstreet","slug":"don-t-know-mime-type-for-path","errorCode":null,"errorMessage":"Don't know MIME type for {path}","messagePattern":"Don't know MIME type for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"abstio/src/io_web.rs","lineNumber":204,"sourceCode":"    for idx in 0..storage.length().unwrap() {\n        keys.push(storage.key(idx).unwrap().unwrap());\n    }\n    keys\n}\n\n/// Returns path on success\npub fn write_file(path: String, contents: String) -> Result<String> {\n    // Make the browser prompt the user to save a local file with arbitrary contents.\n    use wasm_bindgen::JsCast;\n\n    let mimetype = if path.ends_with(\"csv\") {\n        \"text/csv\"\n    } else if path.ends_with(\"json\") {\n        \"application/json\"\n    } else if path.ends_with(\"bin\") {\n        \"application/octet-stream\"\n    } else {\n        bail!(\"Don't know MIME type for {path}\");\n    };\n\n    let data: String = js_sys::JsString::from(format!(\"data:{mimetype};charset=utf-8,\"))\n        .concat(&js_sys::encode_uri_component(&contents))\n        .into();\n\n    // TODO Proper error handling\n    let window = web_sys::window().unwrap();\n    let document = window.document().unwrap();\n    let node = document\n        .create_element(\"a\")\n        .unwrap()\n        .dyn_into::<web_sys::HtmlElement>()\n        .unwrap();\n    node.set_attribute(\"href\", &data).unwrap();\n    node.set_attribute(\"download\", &path).unwrap();\n    document.body().unwrap().append_child(&node).unwrap();\n    node.click();","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/abstio/src/io_web.rs#L186-L222","documentation":"abstio::write_file on web triggers a browser download by constructing a data: URL, which requires a known MIME type. If the filename's extension is not one of the recognized ones (csv, json, bin, etc.), it bails with \"Don't know MIME type for {path}\".","triggerScenarios":"Calling write_file with an extension outside the supported list — e.g. .txt, .xml, .geojson variants not ending exactly in \"json\" (note the check is ends_with(\"json\"), which does cover .geojson), .yaml, or no extension at all.","commonSituations":"Exporting custom formats from an app running in the browser; renaming output files to a new extension; typos in the extension.","solutions":["Rename the output to one of the supported extensions (.csv, .json/.geojson, .bin).","Add a mapping for the needed extension in write_file's MIME table.","Serialize the content into a supported format (e.g. write JSON instead of XML/YAML)."],"exampleFix":"// before\nabstio::write_file(\"summary.txt\", contents);\n// after\nabstio::write_file(\"summary.json\", contents);","handlingStrategy":"validation","validationCode":"fn has_supported_download_ext(path: &str) -> bool {\n    [\"csv\", \"json\", \"bin\"].iter().any(|ext| path.ends_with(ext))\n}","typeGuard":null,"tryCatchPattern":"if !has_supported_download_ext(&filename) {\n    filename.push_str(\".json\"); // coerce to a supported type before exporting\n}\nabstio::write_file(&filename, contents);","preventionTips":["Restrict web exports to csv/json/bin extensions.","Add extensions to write_file's MIME table when adding new export formats.","Test web downloads for every new export feature."],"tags":["web","wasm","download","mime-type"],"backgroundTag":"unsupported-operation","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}