{"record":{"id":"9dbdf242a2719f04","repo":"chenhg5/cc-connect","slug":"create-data-dir-w-9dbdf2","errorCode":null,"errorMessage":"create data dir: %w","messagePattern":"create data dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/matrix/e2ee.go","lineNumber":179,"sourceCode":"\t\t\tslog.Warn(\"matrix: verification helper not available\", \"error\", vErr)\n\t\t} else {\n\t\t\tslog.Info(\"matrix: SAS verification enabled\", \"mode\", \"auto-verify\")\n\t\t}\n\t}\n}\n\nfunc (p *Platform) initCrypto(ctx context.Context, client *mautrix.Client) (*cryptohelper.CryptoHelper, error) {\n\tif client.DeviceID == \"\" {\n\t\treturn nil, fmt.Errorf(\"device ID not available from whoami\")\n\t}\n\n\thomeDir, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get home dir: %w\", err)\n\t}\n\tcryptoDir := filepath.Join(homeDir, \".cc-connect\")\n\tif err := os.MkdirAll(cryptoDir, 0o700); err != nil {\n\t\treturn nil, fmt.Errorf(\"create data dir: %w\", err)\n\t}\n\tdbPath := filepath.Join(cryptoDir, fmt.Sprintf(\"matrix-crypto-%s.db\", client.DeviceID))\n\n\t// Derive a stable pickle key from the access token\n\th := sha256.Sum256([]byte(p.accessToken))\n\tpickleKey := make([]byte, 32)\n\tcopy(pickleKey, h[:])\n\n\treturn p.tryInitCrypto(ctx, client, pickleKey, dbPath, false)\n}\n\nfunc (p *Platform) tryInitCrypto(ctx context.Context, client *mautrix.Client, pickleKey []byte, dbPath string, isRetry bool) (*cryptohelper.CryptoHelper, error) {\n\tch, err := cryptohelper.NewCryptoHelper(client, pickleKey, dbPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create crypto helper: %w\", err)\n\t}\n\tch.DBAccountID = client.UserID.String()\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/matrix/e2ee.go#L161-L197","documentation":"After computing the crypto directory (~/.cc-connect), initCrypto calls os.MkdirAll with mode 0o700 and wraps failure as \"create data dir: %w\". This is a filesystem permission or I/O error preventing creation of the E2EE state database directory. The library needs this directory to persist Matrix crypto (megolm) sessions.","triggerScenarios":"os.MkdirAll(homeDir/.cc-connect, 0o700) fails because a parent path exists as a file, the process lacks write permission on $HOME, the filesystem is read-only, or disk is full.","commonSituations":"Running in a container with read-only root filesystem and no writable volume at $HOME; $HOME owned by another user; ~/.cc-connect path shadowed by a regular file; SELinux/AppArmor denials.","solutions":["Ensure the process's home directory exists and is writable by the running user (chown/chmod)","Check ~/.cc-connect isn't a regular file; remove/rename it if so","Mount a writable volume at the data path in containers (e.g. -v ccdata:/home/user/.cc-connect)","Inspect the wrapped error (permissions vs read-only fs) with ls -ld ~/.cc-connect and mount/dmesg for denials"],"exampleFix":"# before\nls -ld ~/.cc-connect\n# after\nmkdir -p ~/.cc-connect && chown $(whoami) ~/.cc-connect && chmod 700 ~/.cc-connect","handlingStrategy":"try-catch","validationCode":"dir := filepath.Join(home, \".cc-connect\")\nif info, err := os.Stat(dir); err == nil && !info.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", dir)\n}\nif err := unix.Access(dir, unix.W_OK); err != nil {\n    return fmt.Errorf(\"%s is not writable: %v\", dir, err)\n}","typeGuard":"null","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"create data dir\") {\n        slog.Error(\"cannot create crypto store dir\", \"dir\", filepath.Join(home, \".cc-connect\"), \"err\", err)\n        // fall back to a writable temp dir or disable E2EE\n        return nil\n    }\n    return fmt.Errorf(\"init e2ee: %w\", err)\n}","preventionTips":["Provision a writable volume at the crypto data path in containers","Keep the running user's home owned by that user with 700 permissions","Ensure ~/.cc-connect is never replaced by a regular file","Check for read-only mounts or SELinux/AppArmor denials when deploying"],"tags":["matrix","e2ee","filesystem","permissions","mkdir"],"backgroundTag":"mkdir-permission-denied","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"}