chenhg5/cc-connect · error

get home dir: %w

Error message

get home dir: %w

What it means

initCrypto resolves the user's home directory via os.UserHomeDir() to locate the crypto store, and wraps any failure as "get home dir: %w". Go returns an error here when the HOME environment variable (Linux) or equivalent is unset or empty. The library cannot proceed to create the crypto database without it.

Source

Thrown at platform/matrix/e2ee.go:175

	// Initialize SAS verification helper
	if p.autoVerify {
		if vErr := p.initVerification(ctx, ch); vErr != nil {
			slog.Warn("matrix: verification helper not available", "error", vErr)
		} else {
			slog.Info("matrix: SAS verification enabled", "mode", "auto-verify")
		}
	}
}

func (p *Platform) initCrypto(ctx context.Context, client *mautrix.Client) (*cryptohelper.CryptoHelper, error) {
	if client.DeviceID == "" {
		return nil, fmt.Errorf("device ID not available from whoami")
	}

	homeDir, err := os.UserHomeDir()
	if err != nil {
		return nil, fmt.Errorf("get home dir: %w", err)
	}
	cryptoDir := filepath.Join(homeDir, ".cc-connect")
	if err := os.MkdirAll(cryptoDir, 0o700); err != nil {
		return nil, fmt.Errorf("create data dir: %w", err)
	}
	dbPath := filepath.Join(cryptoDir, fmt.Sprintf("matrix-crypto-%s.db", client.DeviceID))

	// Derive a stable pickle key from the access token
	h := sha256.Sum256([]byte(p.accessToken))
	pickleKey := make([]byte, 32)
	copy(pickleKey, h[:])

	return p.tryInitCrypto(ctx, client, pickleKey, dbPath, false)
}

func (p *Platform) tryInitCrypto(ctx context.Context, client *mautrix.Client, pickleKey []byte, dbPath string, isRetry bool) (*cryptohelper.CryptoHelper, error) {
	ch, err := cryptohelper.NewCryptoHelper(client, pickleKey, dbPath)
	if err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Set the HOME environment variable for the process (e.g. Environment=HOME=/home/user in systemd unit)
  2. Run the service under a user with a valid passwd entry (User= in systemd) so UserHomeDir resolves
  3. Use a fully-qualified shell like `getent passwd $(whoami)` to confirm the user has a home directory
  4. Patch/rebuild to allow a configurable crypto data dir instead of deriving from home

Example fix

// systemd unit
# before
[Service]
ExecStart=/usr/bin/cc-connect
// after
[Service]
User=ccconnect
Environment=HOME=/var/lib/ccconnect
ExecStart=/usr/bin/cc-connect
Defensive patterns

Strategy: validation

Validate before calling

if home, err := os.UserHomeDir(); err != nil || home == "" {
    return errors.New("HOME is not set; cannot locate crypto store directory")
}

Type guard

null

Try / catch

crypto, err := p.initCrypto(ctx, client)
if err != nil {
    if strings.Contains(err.Error(), "get home dir") {
        slog.Warn("E2EE unavailable: HOME not set; set HOME or run under a real user")
        return nil // run without encryption
    }
    return fmt.Errorf("init e2ee: %w", err)
}

Prevention

When it happens

Trigger: Calling initE2EE/initCrypto in an environment where os.UserHomeDir() fails: $HOME (and $USER) unset on Linux, or no home directory for the running user.

Common situations: Running cc-connect under systemd with a minimal environment (no HOME); Docker containers running as a non-root user without a passwd entry; CI/cron environments stripping env vars.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/16928ed34af50f14. Report an issue: GitHub.