dagger/dagger · error
key %q is missing an environment name
Error message
key %q is missing an environment name
What it means
userOverlayKeyParts parses user-level config keys and supports an optional "env.<name>." prefix identifying an environment. When the key starts with "env" but has no environment name following it (e.g. "env.modules.foo.settings.x"), this error is thrown because the parser cannot tell which environment the key belongs to.
Source
Thrown at core/workspace/userconfig.go:237
if !ok {
return "", false
}
gitDir = strings.TrimSpace(gitDir)
return gitDir, gitDir != ""
}
// userOverlayKeyParts validates that key addresses user-overridable config and
// returns its parsed path segments. Only module settings may be stored in a
// user-level overlay, always applied or scoped to an environment.
func userOverlayKeyParts(key string) ([]string, error) {
parts, err := splitConfigPath(key)
if err != nil {
return nil, err
}
rest := parts
if len(rest) > 0 && rest[0] == "env" {
if len(rest) < 2 {
return nil, fmt.Errorf("key %q is missing an environment name", key)
}
rest = rest[2:]
}
if len(rest) < 4 || rest[0] != "modules" || rest[2] != "settings" {
return nil, fmt.Errorf("key %q cannot be stored in user-level config; only modules.<name>.settings.* and env.<name>.modules.<name>.settings.* are supported", key)
}
return parts, nil
}
// WriteUserConfigValue sets a config value under [workspaces.<workspaceKey>]
// in user-level config bytes, preserving unrelated sections (e.g. [llm]) and
// other workspace entries. The workspace key is canonicalized; when an entry
// for an equivalent remote spelling already exists, it is updated in place
// rather than duplicated. A non-nil values slice stores a string array
// verbatim; otherwise rawValue is typed like repository config writes.
func WriteUserConfigValue(existing []byte, workspaceKey, key, rawValue string, values []string) ([]byte, error) {
parts, err := userOverlayKeyParts(key)
if err != nil {View on GitHub (pinned to 82ba2681db)
Solutions
- Add the environment name after "env": use "env.<name>.modules.<mod>.settings.<key>"
- If you do not mean an environment, drop the "env" segment and use "modules.<mod>.settings.<key>"
- Split the key on "." and verify segment 2 (index 1) is the environment name, not "modules"
Example fix
// before WriteUserConfigValue(data, "env.modules.foo.settings.timeout", "30") // after WriteUserConfigValue(data, "env.ci.modules.foo.settings.timeout", "30")
Defensive patterns
Strategy: validation
Validate before calling
segs := strings.Split(key, ".")
if segs[0] == "env" && len(segs) < 5 {
return fmt.Errorf("env-scoped keys need: env.<name>.modules.<mod>.settings.<key>")
} Type guard
func isWellFormedEnvKey(key string) bool {
s := strings.Split(key, ".")
return len(s) < 2 || s[0] != "env" || (len(s) >= 5 && s[1] != "" && s[1] != "modules")
} Try / catch
_, err := workspace.WriteUserConfigValue(data, key, wsKey, val)
if err != nil && strings.Contains(err.Error(), "missing an environment name") {
return fmt.Errorf("key %q must include the environment name after 'env'", key)
} Prevention
- Always spell env keys fully: env.<name>.modules.<mod>.settings.<key>
- Build keys from a helper function, never string concatenation by hand
- Unit-test key builders with env-prefixed cases
When it happens
Trigger: Calling WriteUserConfigValue or DeleteUserConfigValue with a key whose first segment is "env" followed by fewer than 2 remaining segments — e.g. "env", "env.x", or "env.modules.foo.settings.x" (env immediately followed by modules).
Common situations: Typing a config key without the environment name ("dagger config set env.modules.x..."); scripting that drops a segment when building keys programmatically; documentation examples copied incompletely.
Related errors
- key %q cannot be stored in user-level config; only modules.<
- key %q is not set in user-level config for workspace %q
- generateModule is called but module config is missing
- workspace port key %q: %w
- unknown sdk config keys found %v
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/0a082dc99e99e1b8.
Report an issue: GitHub.