nginx/nginx · error

NGX_LOG_CRIT

NGX_LOG_CRIT

Error message

<ngx_open_file_n> \"%s\" failed

What it means

Logged by ngx_stream_geo_include_binary_base(): opening the precompiled range base file ('<include>.bin') with ngx_open_file() failed with an errno other than NGX_ENOENT - typically EACCES. Missing files (ENOENT) are silent because the normal case is 'no .bin yet'. The function returns NGX_DECLINED so nginx falls back to parsing the text include file; startup only fails if that also fails.

Source

Thrown at src/stream/ngx_stream_geo_module.c:1371

    ngx_err_t                     err;
    ngx_int_t                     rc;
    ngx_uint_t                    i;
    ngx_file_t                    file;
    ngx_file_info_t               fi;
    ngx_stream_geo_range_t       *range, **ranges;
    ngx_stream_geo_header_t      *header;
    ngx_stream_variable_value_t  *vv;

    ngx_memzero(&file, sizeof(ngx_file_t));
    file.name = *name;
    file.log = cf->log;

    file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (file.fd == NGX_INVALID_FILE) {
        err = ngx_errno;
        if (err != NGX_ENOENT) {
            ngx_conf_log_error(NGX_LOG_CRIT, cf, err,
                               ngx_open_file_n " \"%s\" failed", name->data);
        }
        return NGX_DECLINED;
    }

    if (ctx->outside_entries) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "binary geo range base \"%s\" cannot be mixed with usual entries",
            name->data);
        rc = NGX_ERROR;
        goto done;
    }

    if (ctx->binary_include) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "second binary geo range base \"%s\" cannot be mixed with \"%s\"",
            name->data, ctx->include_name.data);
        rc = NGX_ERROR;

View on GitHub (pinned to 3f6f7824d4)

Solutions

  1. Check the exact path printed in the message and run `ls -l <file>.bin` and `sudo -u <nginx-user> cat <file>.bin` to confirm readability
  2. Fix permissions: `chown <nginx-user> <file>.bin; chmod 644 <file>.bin` (and +x on parent dirs)
  3. Adjust SELinux context (`restorecon`) or the AppArmor profile if applicable
  4. As a workaround delete the .bin - nginx re-parses the text file and regenerates it

Example fix

# before: .bin written by root with 600
$ ls -l /etc/nginx/geo/geo.conf.bin
-rw------- root root /etc/nginx/geo/geo.conf.bin

# after: readable by master process user
$ chown nginx:nginx /etc/nginx/geo/geo.conf.bin
$ chmod 644 /etc/nginx/geo/geo.conf.bin
Defensive patterns

Strategy: validation

Validate before calling

# pre-flight: master-process user must be able to read text + .bin
for f in /etc/nginx/geo/*.conf /etc/nginx/geo/*.conf.bin; do
  [ -e "$f" ] && sudo -u nginx test -r "$f" || echo "UNREADABLE: $f"
done

Prevention

When it happens

Trigger: A `<name>.bin` exists next to the include file but the master process user cannot open it (permission bits, non-searchable parent directory, SELinux/AppArmor denial), so ngx_open_file() returns NGX_INVALID_FILE with err != NGX_ENOENT.

Common situations: The .bin was generated by root with restrictive umask while nginx runs as another user; security modules blocking access; containers with read-only or odd permission mounts.

Related errors


AI-assisted analysis of nginx/nginx@3f6f7824d4 (2026-08-22). Data as JSON: /api/errors/343d6f6d60d7c9f0. Report an issue: GitHub.