a-b-street/abstreet · error

Your clipboard doesn't seem to have GeoJSON. Got

Error message

Your clipboard doesn't seem to have GeoJSON. Got: {}

What it means

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.

Solutions

  1. Re-copy the complete, raw GeoJSON text (starting with { and ending with }) and retry the import.
  2. Validate the text is parseable GeoJSON first (paste into geojson.io or a JSON validator).
  3. Skip the clipboard path: save the GeoJSON to a file and load it directly from disk instead.

Example fix

// before (clipboard)
https://example.com/boundary.geojson
// after (clipboard)
{"type": "FeatureCollection", "features": [...]}
Defensive patterns

Strategy: validation

Validate before calling

let contents = widgetry::tools::get_clipboard()?;
if contents.trim_start().starts_with('{')
    && serde_json::from_str::<serde_json::Value>(&contents)
        .ok()
        .and_then(|v| v.get("type").cloned())
        .map_or(true, |t| t != "FeatureCollection" && t != "Feature")
{
    bail!("clipboard is not GeoJSON");
}

Type guard

fn is_geojson(s: &str) -> bool {
    s.parse::<geojson::GeoJson>().is_ok()
}

Try / catch

match grab_geojson_from_clipboard() {
    Ok(()) => {},
    Err(e) if e.to_string().contains("doesn't seem to have GeoJSON") => {
        eprintln!("Clipboard lacked GeoJSON — copy the raw JSON and retry, or load from file: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/b82e8ee18792c220. Report an issue: GitHub.

Appendix: source

Thrown at map_gui/src/tools/importer.rs:178

                            ],
                        )),
                    }
                }
                _ => unreachable!(),
            },
            _ => Transition::Keep,
        }
    }

    fn draw(&self, g: &mut GfxCtx, _: &A) {
        self.panel.draw(g);
    }
}

fn grab_geojson_from_clipboard() -> Result<()> {
    let contents = widgetry::tools::get_clipboard()?;
    if contents.parse::<geojson::GeoJson>().is_err() {
        bail!(
            "Your clipboard doesn't seem to have GeoJSON. Got: {}",
            contents
        );
    }
    let mut f = fs_err::File::create("boundary.geojson")?;
    write!(f, "{}", contents)?;
    Ok(())
}

fn sanitize_name(x: String) -> String {
    x.replace(" ", "_")
}

fn generate_new_map_name() -> String {
    let mut i = 0;
    loop {
        let name = format!("imported_{}", i);
        if !abstio::file_exists(MapName::new("zz", "oneshot", &name).path()) {

View on GitHub (pinned to 0964f29315)