{"record":{"id":"af7b68347a66d25c","repo":"chenhg5/cc-connect","slug":"kimi-read-sessions-dir-w","errorCode":null,"errorMessage":"kimi: read sessions dir: %w","messagePattern":"kimi: read sessions dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/kimi/kimi.go","lineNumber":358,"sourceCode":"\t\tfilepath.Join(homeDir, \".kimi\", \"sessions\"),\n\t\tfilepath.Join(homeDir, \".kimi-code\", \"sessions\"),\n\t}\n}\n\nfunc listKimiSessions(workDir string) ([]core.AgentSessionInfo, error) {\n\tabsWorkDir, err := filepath.Abs(workDir)\n\tif err != nil {\n\t\tabsWorkDir = workDir\n\t}\n\n\tvar sessions []core.AgentSessionInfo\n\tfor _, sessionsBase := range kimiSessionsBaseDirs() {\n\t\tentries, err := os.ReadDir(sessionsBase)\n\t\tif err != nil {\n\t\t\tif os.IsNotExist(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"kimi: read sessions dir: %w\", err)\n\t\t}\n\n\t\tfor _, entry := range entries {\n\t\t\tif !entry.IsDir() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tprojectDir := filepath.Join(sessionsBase, entry.Name())\n\t\t\tsessionEntries, err := os.ReadDir(projectDir)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, se := range sessionEntries {\n\t\t\t\tif !se.IsDir() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsessionDir := filepath.Join(projectDir, se.Name())\n\t\t\t\tinfo := parseKimiSessionDir(sessionDir, absWorkDir)\n\t\t\t\tif info != nil {","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/kimi/kimi.go#L340-L376","documentation":"listKimiSessions returns this when os.ReadDir on one of kimi's session base directories fails with an error other than NotExist (which is skipped). It means the sessions directory exists but could not be read — typically a permissions problem.","triggerScenarios":"Calling ListSessions (or DeleteSession flows that enumerate) when a kimi sessions base dir exists but ReadDir fails: permission denied on the directory, it is not actually a directory, or an I/O error on the volume.","commonSituations":"Daemon runs as a different user than the one who owns ~/.kimi (or ~/.config/kimi); sessions path replaced by a file; NFS/sshfs mount hiccup; restrictive umask/ACLs after a restore or migration.","solutions":["Fix permissions: `chmod u+rx` the sessions directory and chown it to the daemon user","Confirm the path is a directory (`ls -la`); remove/rename any file shadowing it","Align the daemon's HOME with the user owning the kimi sessions","Check mount health if sessions live on a network volume"],"exampleFix":"// before\n# daemon user cannot read sessions\n// after\nsudo chown -R cc-connect:cc-connect ~/.kimi/sessions\nsudo chmod -R u+rwX ~/.kimi/sessions","handlingStrategy":"try-catch","validationCode":"for _, base := range kimiSessionsBaseDirs() {\n    if st, err := os.Stat(base); err == nil && !st.IsDir() {\n        return fmt.Errorf(\"%s is not a directory\", base)\n    }\n}","typeGuard":null,"tryCatchPattern":"sessions, err := agent.ListSessions(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"read sessions dir\") {\n        log.Printf(\"check permissions/ownership of kimi sessions dir: %v\", err)\n    }\n    return err\n}","preventionTips":["Provision kimi session dirs with correct owner/permissions for the daemon user","Monitor mounts holding session storage for availability","Avoid replacing session directories with files during backups/restores"],"tags":["go","filesystem","permissions","kimi"],"backgroundTag":"permission-denied","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}