lionsoul2014/ip2region · critical
failed to determine xdb version from header: %s
Error message
failed to determine xdb version from header: %s
What it means
At nginx startup, ip2region reads the first bytes of the xdb file to detect its IP format version (IPv2/IPv3/IPv4 structure). xdb_version_from_header returned NULL, meaning the header bytes do not match any known xdb version layout, so the module cannot initialize a searcher. This is a nginx conf-time (NGX_CONF_ERROR) failure that aborts nginx startup.
Source
Thrown at binding/nginx/src/ngx_http_ip2region_module.c:131
}
ip2region_searcher->v_index = NULL;
ip2region_searcher->c_buffer = NULL;
// 检查XDB文件的版本信息以确定IP类型
xdb_header_t *header = xdb_load_header_from_file(db_path);
if (header == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"failed to load xdb header from: %s", db_path);
if(ngx_http_ip2region_is_absolute_path(db_name) != NGX_OK) {
free(db_path);
}
return NGX_CONF_ERROR;
}
xdb_version_t *xdb_version = xdb_version_from_header(header);
if (xdb_version == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"failed to determine xdb version from header: %s", db_path);
xdb_free_header((void *)header);
if(ngx_http_ip2region_is_absolute_path(db_name) != NGX_OK) {
free(db_path);
}
return NGX_CONF_ERROR;
}
// 验证XDB文件版本是否匹配
if (xdb_version->id != expected_version->id) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s expects %s xdb file, but got %s: %s",
directive_name, expected_version->name, xdb_version->name, db_path);
xdb_free_header((void *)header);
if(ngx_http_ip2region_is_absolute_path(db_name) != NGX_OK) {
free(db_path);
}
return NGX_CONF_ERROR;View on GitHub (pinned to c1a1fc7d59)
Solutions
- Verify the file is a genuine, complete ip2region xdb: check `file ip2region.xdb` and size, and re-download from the official data release.
- Confirm the configured path in nginx.conf resolves to the intended file (no typos, correct root-relative resolution).
- Regenerate or re-export the xdb with a maker tool from the same ip2region project version.
- Check the file is not gzip/xz compressed; decompress it before use.
- Confirm read permissions so the header can actually be read fully.
Example fix
# before ip2region_db_file /etc/nginx/data/ip2region.xdb.gz; # after gunzip /etc/nginx/data/ip2region.xdb.gz ip2region_db_file /etc/nginx/data/ip2region.xdb;
Defensive patterns
Strategy: validation
Validate before calling
#!/bin/bash
# run before pointing nginx at the xdb
f=/data/ip2region.xdb
[ -s "$f" ] || { echo "missing/empty xdb"; exit 1; }
[ $(stat -c%s "$f") -ge 256 ] || { echo "xdb too small (truncated?)"; exit 1; }
# a real xdb starts with its structured header; reject compressed/text files
file "$f" | grep -Eqi 'gzip|xz|zip|ASCII text' && { echo 'not a raw xdb'; exit 1; }
echo "xdb header looks loadable" Prevention
- Checksum-verify xdb downloads before deployment.
- Never configure a .gz/.xz archive path directly; decompress first.
- Keep xdb files on stable, worker-readable paths.
- Run `nginx -t` in CI so conf-time failures are caught before deploy.
When it happens
Trigger: The ip2region_db_file/ip2region_db_file_v6 directive points to a file whose header is corrupt, truncated (shorter than the header size), empty, or not an xdb file at all (e.g. a text file, HTML error page from a bad download, or a .xz/.gz archive that was not decompressed).
Common situations: Downloading the xdb with curl that saved an error page; an incomplete/ interrupted download; a file that was renamed but not the actual ip2region xdb; a corrupted copy on a mounted volume; using an old/different data format file.
Related errors
- %s expects %s xdb file, but got %s: %s
- failed to create searcher: %s
- failed to create vector index cached searcher: %s
- failed to create content cached searcher: %s
- failed to load vector index from: %s
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/dd9ba1f29fa3a3bc.
Report an issue: GitHub.