googleapis/mcp-toolbox · error

environment variable not found: %s

Error message

environment variable not found: %s

What it means

Raised by ConfigParser.parseEnv when exactly one required environment variable referenced in the config (via ${VAR} substitution) is missing from the environment. parseEnv substitutes env vars into the raw YAML and collects any placeholders that have no matching env var; a single missing var produces this singular message. Startup fails so the server never runs with silently-unresolved config.

Source

Thrown at cmd/internal/config.go:144

		}

		lastIndex = end
	}
	output.WriteString(input[lastIndex:])

	// Filter out OptionalEnvVars that were also found as required
	var finalOptional []string
	for _, v := range p.OptionalEnvVars {
		if !slices.Contains(p.requiredEnvVars, v) && !slices.Contains(finalOptional, v) {
			finalOptional = append(finalOptional, v)
		}
	}
	p.OptionalEnvVars = finalOptional

	var err error
	if len(missing) > 0 {
		if len(missing) == 1 {
			err = fmt.Errorf("environment variable not found: %s", missing[0])
		} else {
			err = fmt.Errorf("environment variables not found:\n  - %s", strings.Join(missing, "\n  - "))
		}
	}

	return output.String(), err
}

// isInsideComment checks if the given 1-based rune offset in the YAML input is
// within a comment token. Token positions from the lexer are 1-based rune
// offsets, so callers must convert byte offsets before calling this.
func isInsideComment(tokens token.Tokens, runeOffset int) bool {
	for _, t := range tokens {
		if t.Type == token.CommentType && t.Position != nil {
			// Position.Offset points at the "#", but Origin also carries any
			// indentation that precedes it, so measure the length from the "#".
			length := utf8.RuneCountInString(strings.TrimLeft(t.Origin, " \t"))
			if runeOffset >= t.Position.Offset && runeOffset < t.Position.Offset+length {

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Export the named variable in the shell before starting: export DATABASE_URL=...
  2. Use an env file/director (`toolbox --env-file .env`) or your deployment's secret manager to inject the variable.
  3. Fix typos so the ${VAR} name in the config matches the actual environment variable name.
  4. If the variable is truly optional, mark it as an optional env var in the parser config (OptionalEnvVars).

Example fix

# before: config has ${DATABASE_URL}, shell lacks it -> "environment variable not found: DATABASE_URL"
./toolbox --config tools.yaml
# after
export DATABASE_URL="postgres://user:pass@localhost:5432/db"
./toolbox --config tools.yaml
Defensive patterns

Strategy: validation

Validate before calling

// verify required env vars before launching
if os.Getenv("DATABASE_URL") == "" {
    log.Fatal("environment variable not found: DATABASE_URL")
}

Try / catch

if strings.Contains(err.Error(), "environment variable not found:") {
    missing := strings.TrimPrefix(err.Error(), "environment variable not found: ")
    log.Fatalf("set %s in your environment or .env file", missing)
}

Prevention

When it happens

Trigger: Running `toolbox` with a config file containing exactly one ${VAR} (or ${VAR:-} style required reference) whose environment variable is unset, e.g. `connectionString: ${DATABASE_URL}` with DATABASE_URL not exported.

Common situations: Forgetting to source an .env file; deploying with a secret not mounted/injected; renaming a variable in config but not in the shell/CI environment; typos in variable names.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/34d77f45bf299633. Report an issue: GitHub.