{"record":{"id":"b82e8ee18792c220","repo":"a-b-street/abstreet","slug":"your-clipboard-doesn-t-seem-to-have-geojson-got","errorCode":null,"errorMessage":"Your clipboard doesn't seem to have GeoJSON. Got: {}","messagePattern":"Your clipboard doesn't seem to have GeoJSON\\. Got: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_gui/src/tools/importer.rs","lineNumber":178,"sourceCode":"                            ],\n                        )),\n                    }\n                }\n                _ => unreachable!(),\n            },\n            _ => Transition::Keep,\n        }\n    }\n\n    fn draw(&self, g: &mut GfxCtx, _: &A) {\n        self.panel.draw(g);\n    }\n}\n\nfn grab_geojson_from_clipboard() -> Result<()> {\n    let contents = widgetry::tools::get_clipboard()?;\n    if contents.parse::<geojson::GeoJson>().is_err() {\n        bail!(\n            \"Your clipboard doesn't seem to have GeoJSON. Got: {}\",\n            contents\n        );\n    }\n    let mut f = fs_err::File::create(\"boundary.geojson\")?;\n    write!(f, \"{}\", contents)?;\n    Ok(())\n}\n\nfn sanitize_name(x: String) -> String {\n    x.replace(\" \", \"_\")\n}\n\nfn generate_new_map_name() -> String {\n    let mut i = 0;\n    loop {\n        let name = format!(\"imported_{}\", i);\n        if !abstio::file_exists(MapName::new(\"zz\", \"oneshot\", &name).path()) {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_gui/src/tools/importer.rs#L160-L196","documentation":"grab_geojson_from_clipboard reads the system clipboard and requires its contents to parse as GeoJSON, so the imported boundary can be saved to boundary.geojson. If parsing fails it bails echoing the raw clipboard contents for inspection.","triggerScenarios":"Using the map importer's clipboard paste action when the clipboard holds HTML, plain coordinates, a URL, truncated JSON, or GeoJSON copied from a tool that wraps it in extra text.","commonSituations":"Copy operation grabbed a webpage selection instead of the JSON; clipboard contains 'Copy' button output with formatting; OS clipboard managers replacing content; copying only part of a large GeoJSON.","solutions":["Re-copy the complete, raw GeoJSON text (starting with { and ending with }) and retry the import.","Validate the text is parseable GeoJSON first (paste into geojson.io or a JSON validator).","Skip the clipboard path: save the GeoJSON to a file and load it directly from disk instead."],"exampleFix":"// before (clipboard)\nhttps://example.com/boundary.geojson\n// after (clipboard)\n{\"type\": \"FeatureCollection\", \"features\": [...]}","handlingStrategy":"validation","validationCode":"let contents = widgetry::tools::get_clipboard()?;\nif contents.trim_start().starts_with('{')\n    && serde_json::from_str::<serde_json::Value>(&contents)\n        .ok()\n        .and_then(|v| v.get(\"type\").cloned())\n        .map_or(true, |t| t != \"FeatureCollection\" && t != \"Feature\")\n{\n    bail!(\"clipboard is not GeoJSON\");\n}","typeGuard":"fn is_geojson(s: &str) -> bool {\n    s.parse::<geojson::GeoJson>().is_ok()\n}","tryCatchPattern":"match grab_geojson_from_clipboard() {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"doesn't seem to have GeoJSON\") => {\n        eprintln!(\"Clipboard lacked GeoJSON — copy the raw JSON and retry, or load from file: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Copy raw GeoJSON text only — avoid copying from rendered web pages","Paste into a JSON validator before importing","Prefer saving boundaries to a file and loading from disk for large geometries"],"tags":["geojson","clipboard","gui-importer"],"backgroundTag":"json-parse-error","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"}