How to Check if Nginx Variable is Set Without Warning Messages


3 views

When working with Nginx configuration, you might encounter situations where you need to check if a variable is set before assigning a default value. A common approach would be:

if ($foo ~ "^$") {
   set $foo default-value;
}

While this works functionally, it generates annoying runtime warnings:

[warn] using uninitialized "foo" variable

Nginx's configuration parser performs static analysis and emits warnings when it detects potential usage of uninitialized variables. Even though our logic handles the uninitialized case, the parser still sees the variable reference before the set directive.

Instead of globally disabling warnings with uninitialized_variable_warn off, here are more elegant approaches:

Method 1: Using map Directive

The map directive provides a clean way to handle default values:

map $foo $foo_with_default {
    ""      "default-value";
    default $foo;
}

server {
    # Use $foo_with_default instead of $foo
}

Method 2: Using try_files as Workaround

This clever approach leverages try_files behavior:

set $foo "";
try_files $uri $uri/ @set_default;

location @set_default {
    set $foo "default-value";
    # continue with your logic
}

Method 3: Initializing Variables Early

Simply initialize variables at the configuration level:

set $foo "";
if ($foo = "") {
    set $foo "default-value";
}

While all methods work, the map directive is generally the most performant as it's evaluated during configuration parsing. The if block approach requires runtime evaluation.

Here's how you might implement this for a header-based routing scenario:

map $http_x_api_version $api_version {
    ""      "v1";
    default $http_x_api_version;
}

server {
    location /api {
        proxy_pass http://backend_$api_version;
    }
}

When working with Nginx variables, you might encounter situations where you need to check if a variable exists before using it. A common approach is:

if ($foo ~ "^$") {
   set $foo default-value;
}

However, this triggers an annoying runtime warning:

using uninitialized "foo" variable

Nginx evaluates variables when they're used in expressions, even if the expression is checking for their existence. This creates a catch-22 situation where you need to test a variable that technically doesn't exist yet.

Method 1: Using map Directive

The cleanest solution is to use Nginx's map directive which handles unset variables gracefully:

map $foo $foo_with_default {
    default    "default-value";
    ""         "default-value";
    ~.         $foo;
}

# Then use $foo_with_default instead of $foo

Method 2: Two-phase Variable Handling

Another approach is to use an intermediate variable:

set $is_foo_set 0;
if ($foo) {
    set $is_foo_set 1;
}

if ($is_foo_set = 0) {
    set $foo "default-value";
}

Method 3: Using try_files with Named Locations (for specific cases)

For URI handling scenarios, you can use:

location / {
    try_files $uri @fallback;
}

location @fallback {
    set $foo "default-value";
    # rest of your fallback logic
}

The map solution is generally the most efficient as it:

  • Doesn't require multiple conditional checks
  • Works at configuration load time rather than request time
  • Maintains clean configuration without warning suppression