wtfutil/wtf · error

cannot expand user-specific home dir

Error message

cannot expand user-specific home dir

What it means

expandHomeDir expands a leading '~' in a config path to the user's home directory. It only supports the forms '~' and '~/...' (or '~\...'); any other character after the tilde (e.g. '~otheruser/docs') is unsupported and produces this error, because resolving another user's home is not attempted.

Source

Thrown at cfg/config_files.go:176

			os.Exit(1)
		}
	}
}

// Expand expands the path to include the home directory if the path
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
// returned as-is.
func expandHomeDir(path string) (string, error) {
	if path == "" {
		return path, nil
	}

	if path[0] != '~' {
		return path, nil
	}

	if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
		return "", errors.New("cannot expand user-specific home dir")
	}

	dir, err := home()
	if err != nil {
		return "", err
	}

	return filepath.Join(dir, path[1:]), nil
}

// Dir returns the home directory for the executing user.
// An error is returned if a home directory cannot be detected.
func home() (string, error) {
	currentUser, err := user.Current()
	if err != nil {
		return "", err
	}
	if currentUser.HomeDir == "" {

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Use '~' or '~/...' form only; expand other users' homes yourself before calling
  2. Pre-resolve the path with os.UserHomeDir() or os.ExpandEnv and pass an absolute path
  3. Check for stray characters right after '~' in the path string (typo check)

Example fix

// before
home, err := cfg.LoadWtfConfigFile("~alice/.config/wtf/config.yml")
// after
aliceHome, _ := user.Lookup("alice")
home, err := cfg.LoadWtfConfigFile(filepath.Join(aliceHome.HomeDir, ".config/wtf/config.yml"))
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(path, "~") && len(path) > 1 && path[1] != '/' && path[1] != '\\' {
    return errors.New("only ~/ paths are supported, not ~user")
}

Type guard

func isExpandableTildePath(p string) bool {
    return p == "~" || (len(p) > 1 && p[0] == '~' && (p[1] == '/' || p[1] == '\\'))
}

Try / catch

path, err := cfg.ExpandHomeDir(rawPath)
if err != nil {
    log.Fatalf("bad config path %q: %v", rawPath, err)
}

Prevention

When it happens

Trigger: Passing a config path like '~bob/wtf/config.yml' or '~root/...' to WtfConfigDir, LoadWtfConfigFile, chmodConfigFile, or migrateOldConfig; a WTF_CONFIG-style env var or -c flag containing '~username' syntax.

Common situations: Users copying Unix shell tilde-expansion conventions (which support ~user) into wtfutil config paths or launchd/systemd service definitions; typos like '~ name' or '~/~/x'.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/47864fd5529bed9a. Report an issue: GitHub.