{"record":{"id":"e729f4fb4abc75f3","repo":"plandex-ai/plandex","slug":"failed-to-read-the-file-s-v-e729f4","errorCode":null,"errorMessage":"failed to read the file %s: %v","messagePattern":"failed to read the file (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/context_update.go","lineNumber":388,"sourceCode":"\t\t\t\tdefer wg.Done()\n\t\t\t\tsem <- struct{}{}\n\t\t\t\tdefer func() { <-sem }()\n\n\t\t\t\tif _, err := os.Stat(ctx.FilePath); os.IsNotExist(err) {\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tdefer mu.Unlock()\n\n\t\t\t\t\tdeleteIds[ctx.Id] = true\n\t\t\t\t\tnumFilesRemoved++\n\t\t\t\t\ttokenDiffsById[ctx.Id] = -ctx.NumTokens\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tfileContent, err := os.ReadFile(ctx.FilePath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tdefer mu.Unlock()\n\t\t\t\t\terrs = append(errs, fmt.Errorf(\"failed to read the file %s: %v\", ctx.FilePath, err))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfileContent = shared.NormalizeEOL(fileContent)\n\n\t\t\t\tfileInfo, err := os.Stat(ctx.FilePath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tdefer mu.Unlock()\n\t\t\t\t\terrs = append(errs, fmt.Errorf(\"failed to get file info for %s: %v\", ctx.FilePath, err))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsize := fileInfo.Size()\n\n\t\t\t\t// Individual skip checks\n\t\t\t\tif size > shared.MaxContextBodySize {\n\t\t\t\t\tmu.Lock()\n\t\t\t\t\tdefer mu.Unlock()\n","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/context_update.go#L370-L406","documentation":"During the outdated check, each file-type context is read concurrently with os.ReadFile to hash/compare against stored state. If a file that passed the initial os.Stat existence check cannot be read (permission, race with deletion, I/O error), the error is collected into the errs list with the file path.","triggerScenarios":"os.ReadFile(ctx.FilePath) fails after os.Stat succeeded: permission denied on the file, file deleted between stat and read (TOCTOU race), read-only filesystem, or file is a special device/pipe that cannot be read normally.","commonSituations":"CI running as a different user than the one who added context; files on a network mount that dropped; editor/tooling swapping files (atomic rename) mid-check; chmod changes after adding files to context.","solutions":["Fix permissions on the reported file (chmod/chown) or run as a user with read access","If the file no longer exists, remove it from context (plandex context rm) and re-add","Re-run the command — race-related failures usually clear","Check the filesystem/mount health if errors persist across many files"],"exampleFix":"// before: ignoring collected errs\noutdated, err := lib.CheckOutdatedContext(nil, paths)\n// after: ensure all context files are readable before checking\nfor _, c := range contexts {\n    if c.ContextType == shared.ContextFileType {\n        if f, err := os.Open(c.FilePath); err != nil {\n            log.Fatalf(\"cannot read context file %s: %v\", c.FilePath, err)\n        } else { f.Close() }\n    }\n}\noutdated, err := lib.CheckOutdatedContext(contexts, paths)","handlingStrategy":"validation","validationCode":"for _, c := range contexts {\n    if c.ContextType == shared.ContextFileType {\n        f, err := os.Open(c.FilePath)\n        if err != nil {\n            return fmt.Errorf(\"pre-flight: cannot open %s: %w\", c.FilePath, err)\n        }\n        f.Close()\n    }\n}","typeGuard":null,"tryCatchPattern":"outdated, err := lib.CheckOutdatedContext(contexts, paths)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to read the file \") {\n        // extract path, drop it from context or fix perms, then retry\n        return fmt.Errorf(\"fix unreadable context file, then re-run: %w\", err)\n    }\n    return err\n}","preventionTips":["Check file readability before adding files to context","Avoid deleting/moving files while commands run","Run CLI and file owner under the same user in CI","Watch for TOCTOU: stat-then-read races on actively edited files"],"tags":["go","filesystem","permissions","concurrency"],"backgroundTag":"file-read-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}