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

  1. Set HOME explicitly in the environment (docker ENV HOME=/root or export HOME=$PWD)
  2. Pre-set ec.GlobalConfigDir before calling Prepare so the home lookup is skipped entirely
  3. Run as a user with a valid passwd entry / USERPROFILE on Windows
  4. 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

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 nonexist­ent 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.