elastic/elasticsearch · error · IOException
database type marker not found
Error message
database type marker not found
What it means
Thrown by MMDBUtil.getDatabaseType when the DATABASE_TYPE_MARKER byte sequence is not found within the last BUFFER_SIZE bytes of the file. The marker locates the database_type metadata field in the mmdb tail; its absence means the file is not a valid mmdb or is badly corrupted. IOException propagates to the lookup wiring path.
Source
Thrown at modules/ip-location/src/main/java/org/elasticsearch/ingest/geoip/MMDBUtil.java:76
// find the database_type header
int metadataOffset = -1;
int markerOffset = 0;
for (int i = 0; i < tail.length; i++) {
byte b = tail[i];
if (b == DATABASE_TYPE_MARKER[markerOffset]) {
markerOffset++;
} else {
markerOffset = 0;
}
if (markerOffset == DATABASE_TYPE_MARKER.length) {
metadataOffset = i + 1;
break;
}
}
if (metadataOffset == -1) {
throw new IOException("database type marker not found");
}
// read the database type
final int offsetByte = fromBytes(tail[metadataOffset]);
final int type = offsetByte >>> 5;
if (type != 2) { // 2 is the type indicator in the mmdb format for a UTF-8 string
throw new IOException("type must be UTF-8 string");
}
int size = offsetByte & 0x1f;
if (size == 29) {
// then we need to read in yet another byte and add it onto this size
// this can actually occur in practice, a 29+ character type description isn't that hard to imagine
size = 29 + fromBytes(tail[metadataOffset + 1]);
metadataOffset += 1;
} else if (size >= 30) {
// we'd need to read two or three more bytes to get the size, but this means the type length is >=285
throw new IOException("database_type too long [size indicator == " + size + "]");
}View on GitHub (pinned to db6a809a66)
Solutions
- Confirm the file is an mmdb and not still gzipped (use MMDBUtil.isGzip or a manual gunzip check).
- Re-download the database to rule out truncation.
- Validate the file with the official mmdblookup tool.
- If metadata is unusually large, review whether BUFFER_SIZE needs increasing (code change).
Defensive patterns
Strategy: validation
Validate before calling
boolean looksLikeMmdb(Path p) throws IOException {
if (MMDBUtil.isGzip(p)) return false; // still gzipped, not readable as mmdb
long size = Files.size(p);
if (size == 0) return false;
// best-effort: tail must contain the database type marker
return true;
} Try / catch
try {
String type = MMDBUtil.getDatabaseType(path);
} catch (IOException e) {
if (e.getMessage().equals("database type marker not found")) {
// file is not a valid mmdb; re-download or gunzip first
} else throw e;
} Prevention
- Decompress gzipped downloads before reading as mmdb.
- Validate the file with mmdblookup before loading.
- Re-download on truncation.
- Reject non-mmdb files at ingest configuration time.
When it happens
Trigger: getDatabaseType scans tail[] for DATABASE_TYPE_MARKER; markerOffset never reaches the marker length; metadataOffset stays -1 -> throw.
Common situations: A non-mmdb file supplied as a geoip database; a corrupt/truncated mmdb missing its metadata section; a gzipped file that was not decompressed before reading; BUFFER_SIZE smaller than the metadata section (very large metadata).
Related errors
- type must be UTF-8 string
- database_type too long [size indicator == {}]
- failed to skip [{}] bytes while reading [{}]
- checksum mismatch, expected [{}], actual [{}]
- md5 checksum mismatch, expected [{}], actual [{}]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/962b159808a9f2bf.
Report an issue: GitHub.