nginx/nginx · warning

NGX_LOG_WARN

NGX_LOG_WARN

Error message

kqueue change list is filled up

What it means

ngx_kqueue_set_event() buffers change operations in change_list and submits them lazily with the next kevent() wait. When nchanges reaches max_changes (sized by the kqueue_changes directive, default 512), it logs this WARN and immediately flushes the list with a zero-timeout kevent(), then queues the new change, so no functionality is lost. It is a batching/performance hint: frequent occurrences mean the buffer is too small for the connection churn.

Source

Thrown at src/event/modules/ngx_kqueue_module.c:415

    return rc;
}


static ngx_int_t
ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
{
    struct kevent     *kev;
    struct timespec    ts;
    ngx_connection_t  *c;

    c = ev->data;

    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "kevent set event: %d: ft:%i fl:%04Xi",
                   c->fd, filter, flags);

    if (nchanges >= max_changes) {
        ngx_log_error(NGX_LOG_WARN, ev->log, 0,
                      "kqueue change list is filled up");

        ts.tv_sec = 0;
        ts.tv_nsec = 0;

        if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
            == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
            return NGX_ERROR;
        }

        nchanges = 0;
    }

    kev = &change_list[nchanges];

    kev->ident = c->fd;

View on GitHub (pinned to 3f6f7824d4)

Solutions

  1. Raise the buffer: events { kqueue_changes 4096; } sized above peak concurrent event churn.
  2. Re-run the same load and confirm the warnings disappear.
  3. If warnings persist, profile what generates the churn (aggressive upstream reconnects, tiny keepalive timeouts).
  4. No correctness action needed: nginx already flushed and continued.

Example fix

# before
events { worker_connections 4096; }   # kqueue_changes defaults to 512

# after
events {
    worker_connections 4096;
    kqueue_changes 4096;   # buffer above peak churn so forced flushes stop
}
Defensive patterns

Strategy: validation

Validate before calling

# nginx.conf: size the change buffer above peak event churn before load arrives
events {
    kqueue_changes 4096;   # default 512; raise when this warning appears under load
}

Prevention

When it happens

Trigger: Bursts of event add/del/enable operations between event-loop iterations (mass connection setup/teardown, accept storms, many timers) exceeding kqueue_changes, triggering the forced flush path at the top of ngx_kqueue_set_event().

Common situations: Benchmark or traffic spikes with thousands of new connections per second; configurations with many short-lived upstream connections; default kqueue_changes 512 left untouched after worker_connections was raised.

Related errors


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