nginx/nginx · critical

NGX_LOG_EMERG

NGX_LOG_EMERG

Error message

unknown thread pool \"%V\" in %s:%ui

What it means

After config parsing, ngx_thread_pool_init_conf() walks every pool entry created by ngx_thread_pool_add(); entries with threads still 0 were referenced but never defined by a 'thread_pool' directive. The implicit 'default' pool is auto-sized to 32 threads / 65536 queue; any other undefined name aborts startup with this EMERG - 'nginx -t' fails before any worker starts. The %s:%ui in the message is the file and line of the first reference (e.g. the 'aio threads=name;' line recorded in ngx_thread_pool_add).

Source

Thrown at src/core/ngx_thread_pool.c:444

    tpp = tcf->pools.elts;

    for (i = 0; i < tcf->pools.nelts; i++) {

        if (tpp[i]->threads) {
            continue;
        }

        if (tpp[i]->name.len == ngx_thread_pool_default.len
            && ngx_strncmp(tpp[i]->name.data, ngx_thread_pool_default.data,
                           ngx_thread_pool_default.len)
               == 0)
        {
            tpp[i]->threads = 32;
            tpp[i]->max_queue = 65536;
            continue;
        }

        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                      "unknown thread pool \"%V\" in %s:%ui",
                      &tpp[i]->name, tpp[i]->file, tpp[i]->line);

        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}


static char *
ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_str_t          *value;
    ngx_uint_t          i;
    ngx_thread_pool_t  *tp;

    value = cf->args->elts;

View on GitHub (pinned to 3f6f7824d4)

Solutions

  1. Add the missing directive at main context: thread_pool <name> threads=N [max_queue=M];
  2. Fix the reference if the pool exists under a different name - names are matched exactly (case-sensitive)
  3. Run nginx -t and jump to the %s:%ui in the message - it points at the exact line that referenced the unknown pool

Example fix

# before
http {
    server {
        location /files/ {
            root /data;
            aio threads=bigdisk;   # referenced, never defined
        }
    }
}

# after
thread_pool bigdisk threads=32 max_queue=65536;   # main context
http {
    server {
        location /files/ {
            root /data;
            aio threads=bigdisk;
        }
    }
}
Defensive patterns

Strategy: validation

Validate before calling

# CI check: every pool referenced by aio threads= must be defined
refs=$(nginx -T 2>/dev/null | grep -hoE 'aio +threads=[A-Za-z0-9_]+' | sed -E 's/.*threads=//')
for r in $refs; do
  [ "$r" = "default" ] && continue
  nginx -T 2>/dev/null | grep -qE "^thread_pool +$r +threads=" || {
    echo "undefined thread pool: $r"; exit 1; }
done
nginx -t

Prevention

When it happens

Trigger: 'aio threads=bigdisk;' in a location but no 'thread_pool bigdisk threads=N;' at main context; renaming a pool in one place only; generated configs dropping the thread_pool stanza.

Common situations: Adding 'aio threads=<pool>' from documentation examples without the matching directive; splitting configs into includes where the thread_pool stanza gets lost; copy-paste between environments.

Related errors


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