lionsoul2014/ip2region · critical

failed to create searcher: %s

Error message

failed to create searcher: %s

What it means

With cache_policy "file", the module creates a searcher that reads the xdb directly from disk via xdb_new_with_file_only. A non-zero return means the searcher could not be created — almost always because the file cannot be opened/read at runtime by the nginx worker/master user.

Source

Thrown at binding/nginx/src/ngx_http_ip2region_module.c:156

    }

    // 验证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;
    }

    if (strcmp(cache_policy, "file") == 0) {
        err = xdb_new_with_file_only(xdb_version, &ip2region_searcher->searcher, db_path);
        xdb_free_header((void *)header);
        if (err != 0) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "failed to create searcher: %s", db_path);
            if(ngx_http_ip2region_is_absolute_path(db_name) != NGX_OK) {
                free(db_path);
            }
            return NGX_CONF_ERROR;
        }
    } else if (strcmp(cache_policy, "vectorIndex") == 0) {
        ip2region_searcher->v_index = xdb_load_vector_index_from_file(db_path);
        if (ip2region_searcher->v_index == NULL) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "failed to load vector index from: %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;
        }

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Verify the absolute path exists and is readable: `sudo -u www-data cat /path/to/ip2region.xdb >/dev/null`.
  2. chmod/chown the xdb so the nginx worker user can read it (e.g. chmod 644).
  3. Use an absolute path in the ip2region_cache_policy file setup to avoid cwd ambiguity.
  4. Check audit logs for SELinux/AppArmor denials and allow the read.
  5. Re-test with a freshly downloaded xdb to rule out file corruption.

Example fix

# before
ip2region_db_file data/ip2region.xdb;
# after
ip2region_db_file /usr/share/ip2region/ip2region.xdb;
# and ensure: chmod 644 /usr/share/ip2region/ip2region.xdb
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/bash
f=$(awk '/ip2region_db_file /{print $2; exit}' /etc/nginx/nginx.conf | tr -d ';')
sudo -u www-data test -r "$f" && echo OK || echo "nginx user cannot read $f"

Prevention

When it happens

Trigger: xdb_new_with_file_only returns != 0: file path does not exist at that absolute path, permission denied for the nginx user, or an invalid xdb handle/path passed after the earlier checks passed.

Common situations: Relative path resolving against an unexpected working directory for worker processes; file readable by root but not by the nginx worker user (www-data/nginx); SELinux/AppArmor blocking read; file moved after config was validated.

Related errors


AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02). Data as JSON: /api/errors/a39397ce484b6f5c. Report an issue: GitHub.