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
- Export the variable before starting Glance: `export MY_VAR=...` or add it to the systemd unit / compose environment.
- Check exact spelling and case of the variable name inside {{ env.X }}.
- Use `glance config:print` in the target environment to verify substitution works.
- 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
- Pass all referenced env vars explicitly in systemd Environment= or compose environment.
- Remember empty-but-set is valid; unset is the failure — don't confuse the two when debugging.
- Use `glance config:print` in the deploy environment to confirm substitution.
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
- parsing variable: %v
- readFileFromEnv: environment variable %s not found
- readFileFromEnv: file path %s is not absolute
- readFileFromEnv: reading file from %s: %v
- invalid first day of week
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/2d3876b4af7c8e9b.
Report an issue: GitHub.