{"record":{"id":"9144064cf3df7cb8","repo":"chenhg5/cc-connect","slug":"get-home-dir-w-914406","errorCode":null,"errorMessage":"get home dir: %w","messagePattern":"get home dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/matrix/verification.go","lineNumber":287,"sourceCode":"\t}\n\n\t// Clean up the transaction\n\thelper := p.getVerificationHelper()\n\tif helper != nil {\n\t\t_ = helper.DismissVerification(ctx, txnID)\n\t}\n\tslog.Info(\"matrix: verification complete\", \"txn_id\", txnID)\n}\n\n// crossSigningSeedsPath returns the path where cross-signing seeds are persisted.\nfunc (p *Platform) crossSigningSeedsPath() (string, error) {\n\tclient := p.getClient()\n\tif client == nil || client.DeviceID == \"\" {\n\t\treturn \"\", fmt.Errorf(\"matrix: device ID not available\")\n\t}\n\thomeDir, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"get home dir: %w\", err)\n\t}\n\treturn filepath.Join(homeDir, \".cc-connect\", fmt.Sprintf(\"matrix-cross-signing-%s.json\", client.DeviceID)), nil\n}\n\n// setupCrossSigning bootstraps cross-signing for the bot's own device.\n// Without cross-signing, Element shows \"encrypted by a device not verified\n// by its owner\" on messages from the bot.\nfunc (p *Platform) setupCrossSigning(ctx context.Context, ch *cryptohelper.CryptoHelper) {\n\tmach := ch.Machine()\n\n\t// If private keys are already loaded in memory, just sign our device.\n\tif mach.CrossSigningKeys != nil {\n\t\tp.crossSignOwnDevice(ctx, mach)\n\t\treturn\n\t}\n\n\tseedsPath, err := p.crossSigningSeedsPath()\n\tif err != nil {","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/matrix/verification.go#L269-L305","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the HOME environment variable for the daemon (Environment=HOME=/home/bot in the systemd unit)","Run the service as a regular user that has a home directory","In containers, set ENV HOME=/data (or similar writable path) in the Dockerfile","If launching via sudo, use sudo -E or sudo -H to preserve/set HOME"],"exampleFix":"# before (systemd unit)\n[Service]\nExecStart=/usr/local/bin/cc-connect\n\n# after\n[Service]\nUser=ccbot\nEnvironment=HOME=/home/ccbot\nExecStart=/usr/local/bin/cc-connect","handlingStrategy":"validation","validationCode":"if os.Getenv(\"HOME\") == \"\" {\n    // fail fast: set HOME before starting the daemon\n}","typeGuard":null,"tryCatchPattern":"home, err := os.UserHomeDir()\nif err != nil {\n    slog.Error(\"cannot resolve home dir; set HOME env var\", \"err\", err)\n    return err\n}","preventionTips":["Set HOME explicitly in systemd units, containers, and cron jobs","Run the daemon as a user with a real home directory","Prefer an explicit configurable data dir over relying on HOME"],"tags":["matrix","e2ee","cross-signing","home-directory","filesystem"],"backgroundTag":"missing-env-var","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}