hasura/graphql-engine · error · errors.Error
cannot get home directory: %w
Error message
cannot get home directory: %w
What it means
setupGlobalConfig calls os.UserHomeDir() to derive the default global config directory (~/.<GlobalConfigDirName>) and the OS/environment could not provide a home directory. On Unix this happens when $HOME is empty or unset; on Windows when %USERPROFILE% is unavailable. The error wraps the underlying syscall/env lookup failure.
Source
Thrown at cli/global_config.go:121
err = os.WriteFile(filename, b, 0o644)
if err != nil {
return errors.E(op, fmt.Errorf("write file: %w", err))
}
return nil
}
// setupGlobConfig ensures that global config directory and file exists and
// reads it into the GlobalConfig object.
func (ec *ExecutionContext) setupGlobalConfig() error {
var op errors.Op = "cli.ExecutionContext.setupGlobalConfig"
// check if the directory name is set, else default
if len(ec.GlobalConfigDir) == 0 {
ec.Logger.Debug("global config directory is not pre-set, defaulting")
home, err := os.UserHomeDir()
if err != nil {
return errors.E(op, fmt.Errorf("cannot get home directory: %w", err))
}
globalConfigDir := filepath.Join(home, GlobalConfigDirName)
ec.GlobalConfigDir = globalConfigDir
ec.Logger.Debugf("global config directory set as '%s'", ec.GlobalConfigDir)
}
// create the config directory
err := os.MkdirAll(ec.GlobalConfigDir, os.ModePerm)
if err != nil {
return errors.E(op, fmt.Errorf("cannot create global config directory: %w", err))
}
// check if the filename is set, else default
if len(ec.GlobalConfigFile) == 0 {
ec.GlobalConfigFile = filepath.Join(ec.GlobalConfigDir, GlobalConfigFileName)
ec.Logger.Debugf("global config file set as '%s'", ec.GlobalConfigFile)
}View on GitHub (pinned to 724551b9ae)
Solutions
- Set HOME explicitly in the environment (docker ENV HOME=/root or export HOME=$PWD)
- Pre-set ec.GlobalConfigDir before calling Prepare so the home lookup is skipped entirely
- Run as a user with a valid passwd entry / USERPROFILE on Windows
- For services, set Environment=HOME=... in the unit file
Example fix
# before docker run mycli ... # after docker run -e HOME=/tmp mycli ...
Defensive patterns
Strategy: validation
Validate before calling
if ec.GlobalConfigDir == "" {
if home, err := os.UserHomeDir(); err != nil {
ec.GlobalConfigDir = filepath.Join(os.TempDir(), GlobalConfigDirName)
} else {
ec.GlobalConfigDir = filepath.Join(home, GlobalConfigDirName)
}
} Type guard
func hasHomeDir() bool {
if h := os.Getenv("HOME"); h != "" {
return true
}
_, err := os.UserHomeDir()
return err == nil
} Try / catch
if err := ec.Prepare(ctx); err != nil {
if strings.Contains(err.Error(), "cannot get home directory") {
ec.GlobalConfigDir = filepath.Join(os.TempDir(), GlobalConfigDirName)
return ec.Prepare(ctx)
}
return err
} Prevention
- Always set HOME explicitly in Dockerfiles and systemd units
- Pre-set GlobalConfigDir in embedded/programmatic usage to skip the lookup
- Fail fast with a clear message when HOME is missing rather than deep in Prepare
When it happens
Trigger: Running the CLI with HOME unset or empty (common in minimal Docker scratch/alpine images, systemd services, CI runners, or `sudo -E` stripping env) so len(ec.GlobalConfigDir) == 0 forces the UserHomeDir lookup to fail.
Common situations: Docker containers without an explicit HOME env var, Kubernetes pods running as a nonexistent UID with no HOME, CI pipelines, or running under a service manager that does not set user environment variables.
Related errors
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/5cad718e28769192.
Report an issue: GitHub.