chenhg5/cc-connect · error

get home dir: %w

Error message

get home dir: %w

What it means

crossSigningSeedsPath wraps an os.UserHomeDir() failure with "get home dir: %w". The cross-signing seed file is stored under ~/.cc-connect, so the process must be able to determine the user's home directory. The error is wrapped, preserving the OS-level cause.

Source

Thrown at platform/matrix/verification.go:287

	}

	// Clean up the transaction
	helper := p.getVerificationHelper()
	if helper != nil {
		_ = helper.DismissVerification(ctx, txnID)
	}
	slog.Info("matrix: verification complete", "txn_id", txnID)
}

// crossSigningSeedsPath returns the path where cross-signing seeds are persisted.
func (p *Platform) crossSigningSeedsPath() (string, error) {
	client := p.getClient()
	if client == nil || client.DeviceID == "" {
		return "", fmt.Errorf("matrix: device ID not available")
	}
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return "", fmt.Errorf("get home dir: %w", err)
	}
	return filepath.Join(homeDir, ".cc-connect", fmt.Sprintf("matrix-cross-signing-%s.json", client.DeviceID)), nil
}

// setupCrossSigning bootstraps cross-signing for the bot's own device.
// Without cross-signing, Element shows "encrypted by a device not verified
// by its owner" on messages from the bot.
func (p *Platform) setupCrossSigning(ctx context.Context, ch *cryptohelper.CryptoHelper) {
	mach := ch.Machine()

	// If private keys are already loaded in memory, just sign our device.
	if mach.CrossSigningKeys != nil {
		p.crossSignOwnDevice(ctx, mach)
		return
	}

	seedsPath, err := p.crossSigningSeedsPath()
	if err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Set the HOME environment variable for the daemon (Environment=HOME=/home/bot in the systemd unit)
  2. Run the service as a regular user that has a home directory
  3. In containers, set ENV HOME=/data (or similar writable path) in the Dockerfile
  4. If launching via sudo, use sudo -E or sudo -H to preserve/set HOME

Example fix

# before (systemd unit)
[Service]
ExecStart=/usr/local/bin/cc-connect

# after
[Service]
User=ccbot
Environment=HOME=/home/ccbot
ExecStart=/usr/local/bin/cc-connect
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("HOME") == "" {
    // fail fast: set HOME before starting the daemon
}

Try / catch

home, err := os.UserHomeDir()
if err != nil {
    slog.Error("cannot resolve home dir; set HOME env var", "err", err)
    return err
}

Prevention

When it happens

Trigger: os.UserHomeDir() fails inside crossSigningSeedsPath because $HOME is unset/empty (typical for daemons and systemd services) or on Windows the profile directory cannot be resolved.

Common situations: Running cc-connect as a systemd service without HOME set; running in a Docker container with no HOME env var; executing as a system user with no home directory; stripped environment under sudo/su.

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/9144064cf3df7cb8. Report an issue: GitHub.