plandex-ai/plandex · error

failed to open file %s: %w

Error message

failed to open file %s: %w

What it means

readImageTokensForDefsOnly opens the image file with os.Open to read its header bytes for token estimation; an open failure is wrapped with this message using %w so the underlying error (e.g. *fs.PathError) is preserved for errors.Is/As checks. It means the image token estimator could not even open the file.

Source

Thrown at app/cli/lib/context_shared.go:180

			mapMu.Unlock()
			errCh <- nil
		}(batch)
	}

	for i := 0; i < len(mapInputBatches); i++ {
		err := <-errCh
		if err != nil {
			return nil, err
		}
	}

	return allMapBodies, nil
}

func readImageTokensForDefsOnly(path string, size int64, detail openai.ImageURLDetail, headerBytes int64) (int, error) {
	file, err := os.Open(path)
	if err != nil {
		return 0, fmt.Errorf("failed to open file %s: %w", path, err)
	}
	defer file.Close()

	tokens, err := shared.GetImageTokensFromHeader(file, detail, headerBytes)
	if err != nil {
		tokens = shared.GetImageTokensEstimateFromBytes(size)
	}
	return tokens, nil
}

func printSkippedFilesMsg(
	filesSkippedTooLarge []filePathWithSize,
	filesSkippedAfterSizeLimit []string,
	mapFilesTruncatedTooLarge []filePathWithSize,
	mapFilesSkippedAfterSizeLimit []string,
) {
	fmt.Println()
	fmt.Println(getSkippedFilesMsg(filesSkippedTooLarge, filesSkippedAfterSizeLimit, mapFilesTruncatedTooLarge, mapFilesSkippedAfterSizeLimit))

View on GitHub (pinned to e2d772072e)

Solutions

  1. Verify the path exists and is a regular readable file (not a directory or broken symlink)
  2. Fix permissions on the image file
  3. If mapping many files concurrently and seeing 'too many open files', raise ulimit -n or reduce concurrency

Example fix

// before
file, err := os.Open(path)
if err != nil {
    return 0, fmt.Errorf("failed to open file %s: %w", path, err)
}
// after — clearer diagnostics for common causes
file, err := os.Open(path)
if err != nil {
    if os.IsNotExist(err) {
        return 0, fmt.Errorf("image file %s does not exist", path)
    }
    if os.IsPermission(err) {
        return 0, fmt.Errorf("permission denied reading image %s", path)
    }
    return 0, fmt.Errorf("failed to open file %s: %w", path, err)
}
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil {
    return fmt.Errorf("image %s missing: %w", path, err)
}
if info.IsDir() {
    return fmt.Errorf("%s is a directory, not an image", path)
}
probe, err := os.Open(path)
if err != nil {
    return fmt.Errorf("image %s not readable: %w", path, err)
}
probe.Close()

Type guard

func canOpenFile(path string) bool {
    f, err := os.Open(path)
    if err != nil { return false }
    f.Close()
    return true
}

Try / catch

file, err := os.Open(path)
if err != nil {
    var pathErr *fs.PathError
    if errors.As(err, &pathErr) && errors.Is(err, syscall.EMFILE) {
        return 0, fmt.Errorf("too many open files; reduce concurrency")
    }
    return 0, fmt.Errorf("failed to open file %s: %w", path, err)
}

Prevention

When it happens

Trigger: os.Open(path) fails inside readImageTokensForDefsOnly — file does not exist, permission denied, path is a directory, or too many open files (EMFILE) during heavy batch reads. Called from getMapFileDetails for image files.

Common situations: Broken symlinks to images; images moved/deleted between path resolution and read; hitting the process open-file limit when mapping thousands of files.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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