{"record":{"id":"e59a86293c9a3031","repo":"elastic/elasticsearch","slug":"unsupported-symbol","errorCode":null,"errorMessage":"unsupported symbol [","messagePattern":"unsupported symbol \\[","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/utils/Geohash.java","lineNumber":332,"sourceCode":"            }\n        }\n        return (l << 4) | length;\n    }\n\n    /**\n     * Encode to a morton long value from a given geohash string\n     */\n    public static long mortonEncode(final String hash) {\n        if (hash.isEmpty()) {\n            throw new IllegalArgumentException(\"empty geohash\");\n        }\n        int level = 11;\n        long b;\n        long l = 0L;\n        for (char c : hash.toCharArray()) {\n            b = (long) (BASE_32_STRING.indexOf(c));\n            if (b < 0) {\n                throw new IllegalArgumentException(\"unsupported symbol [\" + c + \"] in geohash [\" + hash + \"]\");\n            }\n            l |= (b << ((level-- * 5) + (MORTON_OFFSET - 2)));\n            if (level < 0) {\n                // We cannot handle more than 12 levels\n                break;\n            }\n        }\n        return BitUtil.flipFlop(l);\n    }\n\n    /** approximate width of geohash tile for a specific precision in degrees */\n    public static double lonWidthInDegrees(int precision) {\n        return precisionToLonWidth[precision];\n    }\n\n    /** approximate height of geohash tile for a specific precision in degrees */\n    public static double latHeightInDegrees(int precision) {\n        return precisionToLatHeight[precision];","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/Geohash.java#L314-L350","documentation":"Thrown by Geohash.mortonEncode(String) when a character in the geohash is not found in the base-32 alphabet. Elasticsearch geohashes use the standard base-32 set: digits 0-9 and lowercase letters bcdefghjkmnpqrstuvwxyz — notably excluding 'a', 'i', 'l', and 'o' to avoid confusion with digits. Uppercase letters also fail because indexOf is case-sensitive.","triggerScenarios":"Calling `Geohash.mortonEncode(hash)` (or toPoint/toBoundingBox) where hash contains any character outside {0-9, b-z minus a/i/l/o}. The offending character is named in the message.","commonSituations":"Uppercase geohashes ('BCDE' instead of 'bcde'); typos including the excluded vowels a/i/l/o; non-geohash strings (UUIDs, hex strings) mistakenly passed as geohashes; mixed-case or whitespace-contaminated input.","solutions":["Lowercase and trim the geohash before encoding: `hash = hash.trim().toLowerCase(Locale.ROOT);`","Strip or reject the excluded vowels (a, i, l, o) — common OCR/copy-paste substitutions for 0/1.","Validate the string against the allowed alphabet before calling mortonEncode."],"exampleFix":"// before\nlong m = Geohash.mortonEncode(\"ABCD1234\"); // throws — uppercase + 'A' not in alphabet\n\n// after\nString clean = hash.trim().toLowerCase(Locale.ROOT)\n    .replace(\"a\", \"\").replace(\"i\", \"\").replace(\"l\", \"\").replace(\"o\", \"\");\nlong m = Geohash.mortonEncode(clean);","handlingStrategy":"validation","validationCode":"String clean = hash == null ? \"\" : hash.trim().toLowerCase(Locale.ROOT);\nif (clean.chars().anyMatch(c -> \"0123456789bcdefghjkmnpqrstuvwxyz\".indexOf(c) < 0)) {\n    throw new IllegalArgumentException(\"invalid geohash character in: \" + hash);\n}\nreturn Geohash.mortonEncode(clean);","typeGuard":"static boolean isValidGeohashString(String hash) {\n    if (hash == null || hash.isEmpty()) return false;\n    String alphabet = \"0123456789bcdefghjkmnpqrstuvwxyz\";\n    for (char c : hash.toCharArray()) {\n        if (alphabet.indexOf(Character.toLowerCase(c)) < 0) return false;\n    }\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Lowercase geohashes before encoding — the alphabet is case-sensitive.","Strip whitespace and the excluded vowels (a, i, l, o) at ingestion.","Guard against non-geohash strings (UUIDs, hex) being routed into geohash APIs."],"tags":["geometry","geohash","validation","base32","character-encoding","libs-geo"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}