{"record":{"id":"34d77f45bf299633","repo":"googleapis/mcp-toolbox","slug":"environment-variable-not-found-s","errorCode":null,"errorMessage":"environment variable not found: %s","messagePattern":"environment variable not found: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/internal/config.go","lineNumber":144,"sourceCode":"\t\t}\n\n\t\tlastIndex = end\n\t}\n\toutput.WriteString(input[lastIndex:])\n\n\t// Filter out OptionalEnvVars that were also found as required\n\tvar finalOptional []string\n\tfor _, v := range p.OptionalEnvVars {\n\t\tif !slices.Contains(p.requiredEnvVars, v) && !slices.Contains(finalOptional, v) {\n\t\t\tfinalOptional = append(finalOptional, v)\n\t\t}\n\t}\n\tp.OptionalEnvVars = finalOptional\n\n\tvar err error\n\tif len(missing) > 0 {\n\t\tif len(missing) == 1 {\n\t\t\terr = fmt.Errorf(\"environment variable not found: %s\", missing[0])\n\t\t} else {\n\t\t\terr = fmt.Errorf(\"environment variables not found:\\n  - %s\", strings.Join(missing, \"\\n  - \"))\n\t\t}\n\t}\n\n\treturn output.String(), err\n}\n\n// isInsideComment checks if the given 1-based rune offset in the YAML input is\n// within a comment token. Token positions from the lexer are 1-based rune\n// offsets, so callers must convert byte offsets before calling this.\nfunc isInsideComment(tokens token.Tokens, runeOffset int) bool {\n\tfor _, t := range tokens {\n\t\tif t.Type == token.CommentType && t.Position != nil {\n\t\t\t// Position.Offset points at the \"#\", but Origin also carries any\n\t\t\t// indentation that precedes it, so measure the length from the \"#\".\n\t\t\tlength := utf8.RuneCountInString(strings.TrimLeft(t.Origin, \" \\t\"))\n\t\t\tif runeOffset >= t.Position.Offset && runeOffset < t.Position.Offset+length {","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/cmd/internal/config.go#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Export the named variable in the shell before starting: export DATABASE_URL=...","Use an env file/director (`toolbox --env-file .env`) or your deployment's secret manager to inject the variable.","Fix typos so the ${VAR} name in the config matches the actual environment variable name.","If the variable is truly optional, mark it as an optional env var in the parser config (OptionalEnvVars)."],"exampleFix":"# before: config has ${DATABASE_URL}, shell lacks it -> \"environment variable not found: DATABASE_URL\"\n./toolbox --config tools.yaml\n# after\nexport DATABASE_URL=\"postgres://user:pass@localhost:5432/db\"\n./toolbox --config tools.yaml","handlingStrategy":"validation","validationCode":"// verify required env vars before launching\nif os.Getenv(\"DATABASE_URL\") == \"\" {\n    log.Fatal(\"environment variable not found: DATABASE_URL\")\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"environment variable not found:\") {\n    missing := strings.TrimPrefix(err.Error(), \"environment variable not found: \")\n    log.Fatalf(\"set %s in your environment or .env file\", missing)\n}","preventionTips":["Keep a committed .env.example listing every ${VAR} the config needs.","Source the env file (set -a; . .env; set +a) before starting toolbox.","In CI, bind all required secrets before the toolbox step.","Grep the config for ${...} placeholders and diff against the environment at deploy time."],"tags":["config","environment","env-var","startup"],"backgroundTag":"missing-env-var","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}