plandex-ai/plandex · error

failed to get file info for %s: %v

Error message

failed to get file info for %s: %v

What it means

This error is produced when os.Stat fails on a file already registered as a file-type context during a context refresh. The file passed the initial IsNotExist check and ReadFile, but stat immediately afterward failed, so the library cannot determine its size for the MaxContextBodySize skip checks. It wraps the underlying os error (permission, race deletion, etc.) with the file path.

Source

Thrown at app/cli/lib/context_update.go:397

					numFilesRemoved++
					tokenDiffsById[ctx.Id] = -ctx.NumTokens
					return
				}

				fileContent, err := os.ReadFile(ctx.FilePath)
				if err != nil {
					mu.Lock()
					defer mu.Unlock()
					errs = append(errs, fmt.Errorf("failed to read the file %s: %v", ctx.FilePath, err))
					return
				}
				fileContent = shared.NormalizeEOL(fileContent)

				fileInfo, err := os.Stat(ctx.FilePath)
				if err != nil {
					mu.Lock()
					defer mu.Unlock()
					errs = append(errs, fmt.Errorf("failed to get file info for %s: %v", ctx.FilePath, err))
					return
				}
				size := fileInfo.Size()

				// Individual skip checks
				if size > shared.MaxContextBodySize {
					mu.Lock()
					defer mu.Unlock()

					filesSkippedTooLarge = append(filesSkippedTooLarge, filePathWithSize{Path: ctx.FilePath, Size: size})
					return
				}
				if totalSize+size > shared.MaxContextBodySize {
					mu.Lock()
					defer mu.Unlock()

					filesSkippedAfterSizeLimit = append(filesSkippedAfterSizeLimit, ctx.FilePath)
					return

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped %v cause: if it is a permission error, fix chmod/chown or run with sufficient privileges.
  2. Re-run the command if the file was being deleted concurrently; ensure no build/watch process is mutating files during the scan.
  3. If the file is genuinely gone, remove it from the context (add via the context add command again or restart) so the deleteIds path handles it instead.
  4. For network mounts, verify mount health and retry.

Example fix

// before
cat missing-or-locked.txt > /dev/null  # permission denied
# after
chmod u+r app/config.yaml  # or fix ownership before refreshing context
Defensive patterns

Strategy: retry

Validate before calling

if _, err := os.Stat(path); err != nil { return fmt.Errorf("context file %s not statable before refresh: %w", path, err) }

Try / catch

if err := refreshContext(ctx); err != nil {
    if strings.Contains(err.Error(), "failed to get file info") {
        // log wrapped cause, retry once after settling concurrent writers
    }
}

Prevention

When it happens

Trigger: os.Stat(ctx.FilePath) returns a non-IsNotExist error inside the per-file goroutine of checkOutdatedAndMaybeUpdateContext, typically after the file was read successfully but then vanished or permissions changed mid-scan.

Common situations: File deleted between the IsNotExist pre-check/ReadFile and the Stat call by another process (build tooling, git operations); permission bits changed on the file or parent directory; file on a flaky/network mount; running as a user without read access after an ACL change.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/6e3cc89e71f55b6a. Report an issue: GitHub.