hashicorp/nomad · warning · ErrVariablePathNotFound

variable not found

Error message

variable not found

What it means

ErrVariablePathNotFound is the sentinel error (message "variable not found") returned by Variables().Read and Variables().GetVariableItems when the queried variable path does not exist on the server — the API returns no variable and readInternal yields a nil v. It is exported so callers can compare with errors.Is instead of matching strings.

Source

Thrown at api/variables.go:25

	"encoding/json"
	"errors"
	"fmt"
	"maps"
	"net/http"
	"strings"
)

const (
	// ErrVariableNotFound was used as the content of an error string.
	//
	// Deprecated: use ErrVariablePathNotFound instead.
	ErrVariableNotFound = "variable not found"
)

var (
	// ErrVariablePathNotFound is returned when trying to read a variable that
	// does not exist.
	ErrVariablePathNotFound = errors.New("variable not found")
)

// Variables is used to access variables.
type Variables struct {
	client *Client
}

// Variables returns a new handle on the variables.
func (c *Client) Variables() *Variables {
	return &Variables{client: c}
}

// Create is used to create a variable.
func (vars *Variables) Create(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) {
	v.Path = cleanPathString(v.Path)
	var out Variable
	wm, err := vars.client.put("/v1/var/"+v.Path, v, &out, qo)
	if err != nil {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the exact variable path (including namespace and 'nomad/jobs/...' prefix) with nomad var list or the UI.
  2. Create the variable first via Create/Update (or `nomad var put`) before reading.
  3. Compare with errors.Is(err, api.ErrVariablePathNotFound) and provide a default/fallback instead of failing.
  4. Check the QueryOptions.Namespace matches where the variable lives, and that the token's ACL grants read on it.

Example fix

// before
v, _, err := client.Variables().Read("nomad/jobs/app/config", nil)
if err != nil { return err }
// after
v, _, err := client.Variables().Read("nomad/jobs/app/config", nil)
if errors.Is(err, api.ErrVariablePathNotFound) {
    v = defaultVar // fall back when the variable doesn't exist yet
} else if err != nil {
    return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

import "errors"
import "github.com/hashicorp/nomad/api"

// pre-check via List to see if the path exists
vars, _, err := client.Variables().List(nil, nil)
exists := false
if err == nil {
    for _, v := range vars {
        if v.Path == "nomad/jobs/app/config" { exists = true; break }
    }
}

Type guard

func isVarNotFound(err error) bool {
    return errors.Is(err, api.ErrVariablePathNotFound)
}

Try / catch

v, _, err := client.Variables().Read(path, nil)
switch {
case errors.Is(err, api.ErrVariablePathNotFound):
    v = createOrUseDefault(path)
case err != nil:
    return err
}

Prevention

When it happens

Trigger: Calling client.Variables().Read(path, q) or GetVariableItems(path, q) for a path that was never created or was deleted/purged; reading a path in a namespace where it doesn't exist; a typo in the variable path (e.g. wrong namespace prefix or missing 'nomad/jobs' segment).

Common situations: Job templates reading variables whose path was misconfigured; CI reading a variable before the provisioning step that creates it; ACL/namespace differences making an existing variable invisible to the caller's token; GC removing stale job variables.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0c8fb5a5042159f4. Report an issue: GitHub.