glanceapp/glance · error

environment variable %s not found

Error message

environment variable %s not found

What it means

Thrown by parseConfigVariableOfType for {{ env.NAME }} expressions when os.LookupEnv reports the variable is not set at all. Deliberately distinguishes 'unset' from 'set to empty string' — an empty-but-set variable is accepted. Only fires when the variable name matches envVariableNamePattern (otherwise the original text is kept unchanged).

Source

Thrown at internal/glance/config.go:199

	if err != nil {
		return nil, err
	}

	return replaced, nil
}

// When the bool return value is true, it indicates that the caller should use the original value
func parseConfigVariableOfType(variableType, variableName string) (string, bool, error) {
	switch variableType {
	case configVarTypeEnv:
		if !envVariableNamePattern.MatchString(variableName) {
			return "", true, nil
		}

		v, found := os.LookupEnv(variableName)
		if !found {
			return "", false, fmt.Errorf("environment variable %s not found", variableName)
		}

		return v, false, nil
	case configVarTypeSecret:
		secretPath := filepath.Join("/run/secrets", variableName)
		secret, err := os.ReadFile(secretPath)
		if err != nil {
			return "", false, fmt.Errorf("reading secret file: %v", err)
		}

		return strings.TrimSpace(string(secret)), false, nil
	case configVarTypeFileFromEnv:
		if !envVariableNamePattern.MatchString(variableName) {
			return "", true, nil
		}

		filePath, found := os.LookupEnv(variableName)
		if !found {

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Export the variable before starting Glance: `export MY_VAR=...` or add it to the systemd unit / compose environment.
  2. Check exact spelling and case of the variable name inside {{ env.X }}.
  3. Use `glance config:print` in the target environment to verify substitution works.
  4. Alternatively switch to {{ secret.NAME }} with a file under /run/secrets for container deployments.

Example fix

# docker-compose.yml (before)
services:
  glance:
    environment:
      - TZ=${TZ}

# after — pass the referenced variable into the container
services:
  glance:
    environment:
      - TZ=${TZ}
      - MY_VAR=${MY_VAR}
Defensive patterns

Strategy: validation

Validate before calling

set -e
: "${GLANCE_HOST:?}" "${GLANCE_TOKEN:?}"   # expands to: GLANCE_TOKEN: parameter null or not set
# or enumerate every referenced var:
for var in $(grep -oE '\{\{ *env\.[A-Za-z_][A-Za-z0-9_]* *\}\}' glance.yml | sed -E 's/.*env\.([A-Za-z0-9_]+).*/\1/'); do
  printenv "$var" >/dev/null || { echo "missing: $var"; exit 1; }
done

Prevention

When it happens

Trigger: glance.yml contains {{ env.MY_VAR }} and MY_VAR is not present in the process environment when Glance starts (systemd unit, Docker container, or shell where it was never exported).

Common situations: Starting Glance via systemd/docker-compose without passing the env vars referenced in config; CI pipelines lacking secrets; case-sensitivity mistakes (env.my_var vs env.MY_VAR); deploying the same glance.yml to a host missing the variable.

Related errors


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/2d3876b4af7c8e9b. Report an issue: GitHub.