a-b-street/abstreet · error
CityName::new( , ) has a country code that isn't two letters
Error message
CityName::new({}, {}) has a country code that isn't two letters What it means
CityName::new validates that the country argument is exactly two characters (an ISO 3166-1 alpha-2 code, lowercase, or 'zz' for imaginary cities) because the country code is used as a directory name in path construction. Passing a longer (or shorter) string panics with this message.
Solutions
- Pass a valid two-letter ISO 3166-1 alpha-2 lowercase code (e.g. 'us', 'gb', 'zz' for test cities)
- Use CityName::parse('us/seattle') or the built-in constructors like CityName::seattle() / MapName::seattle(map) instead of hand-building names
- Rename any non-two-letter directories under data/system/ or importer/config/ so directory scans don't produce invalid codes
- Validate the country string before calling: check country.len() == 2 and use CityName::parse or your own Result-returning wrapper for external input
Example fix
// before
let city = CityName::new("usa", "seattle"); // panics
// after
let city = CityName::new("us", "seattle");
// or validated:
assert_eq!(country.len(), 2);
let city = CityName::parse(&format!("{}/{}", country, city_name))?; Defensive patterns
Strategy: validation
Validate before calling
fn valid_country_code(country: &str) -> bool {
country.len() == 2 && country.chars().all(|c| c.is_ascii_lowercase())
}
// call only if valid_country_code(country) else handle/reprompt Type guard
fn as_country_code(s: &str) -> Option<&str> {
(s.len() == 2 && s.chars().all(|c| c.is_ascii_lowercase())).then_some(s)
} Try / catch
let city = std::panic::catch_unwind(|| CityName::new(country, city))
.map_err(|_| anyhow::anyhow!("country code '{}' must be two letters", country))?; Prevention
- Always use ISO 3166-1 alpha-2 lowercase codes ('us', 'gb', 'zz' for imaginary cities)
- Prefer CityName::parse or built-in constructors (CityName::seattle, MapName::seattle) over manual construction
- Keep directories under data/system/ and importer/config/ named with two-letter codes only
- Validate external/user-supplied country strings before passing to CityName::new or MapName::new
When it happens
Trigger: Calling CityName::new(country, city), MapName::new(country, city, map), or CityName::parse with a country string whose byte length is not 2 — e.g. 'usa', 'US' is fine length-wise but 'USA', 'United States', or an empty string will panic. list_all_cities_locally / list_all_cities_from_importer_config also hit this if a directory under data/system/ or importer/config/ is not a two-letter code.
Common situations: Hardcoding 'usa' instead of 'us', using full country names, creating a stray misnamed directory (e.g. data/system/misc/) that gets scanned as a country, or user-supplied input passed straight into CityName::new.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- This build of A/B Street stores player data in…
- Can't find the data/ directory
- Couldn't read_json( )
- Couldn't read_binary
- Couldn't read_object
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/7916fe0c851b3e04.
Report an issue: GitHub.
Appendix: source
Thrown at abstio/src/abst_paths.rs:83
format!("{dir}/{p}")
}
}
/// A single city is identified using this.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct CityName {
/// A two letter lowercase country code, from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2.
/// To represent imaginary/test cities, use the code `zz`.
pub country: String,
/// The name of the city, in filename-friendly form -- for example, "tel_aviv".
pub city: String,
}
impl CityName {
/// Create a CityName from a country code and city.
pub fn new(country: &str, city: &str) -> CityName {
if country.len() != 2 {
panic!(
"CityName::new({}, {}) has a country code that isn't two letters",
country, city
);
}
CityName {
country: country.to_string(),
city: city.to_string(),
}
}
/// Convenient constructor for the main city of the game.
pub fn seattle() -> CityName {
CityName::new("us", "seattle")
}
/// Returns all city names available locally.
fn list_all_cities_locally() -> Vec<CityName> {
let mut cities = Vec::new();View on GitHub (pinned to 0964f29315)