plandex-ai/plandex · error

error checking if %s is a subpath of %s: %s

Error message

error checking if %s is a subpath of %s: %s

What it means

ParseInputPaths checks each user-supplied path to see whether it is a subpath of one of the original fileOrDirPaths using fs.IsSubpathOf. If that filesystem/path check errors, the failure is wrapped with this message identifying both the child path and the parent candidate. It means path normalization failed before any context was loaded.

Source

Thrown at app/cli/lib/context_paths.go:31

	LoadParams     *types.LoadContextParams
}

func ParseInputPaths(params ParseInputPathsParams) ([]string, error) {
	fileOrDirPaths := params.FileOrDirPaths
	baseDir := params.BaseDir
	projectPaths := params.ProjectPaths
	loadParams := params.LoadParams

	resPaths := []string{}

	for path := range projectPaths.AllPaths {
		// see if it's a child of any of the fileOrDirPaths
		found := false
		for _, p := range fileOrDirPaths {
			var err error
			found, err = fs.IsSubpathOf(p, path, baseDir)
			if err != nil {
				return nil, fmt.Errorf("error checking if %s is a subpath of %s: %s", path, p, err)
			}
			if found {
				break
			}
		}

		if !found {
			continue
		}

		if projectPaths.AllDirs[path] {
			if !(loadParams.Recursive || loadParams.NamesOnly || loadParams.DefsOnly) {
				// log.Println("path", path, "info.Name()", info.Name())
				return nil, fmt.Errorf("cannot process directory %s: requires --recursive/-r, --tree, or --map flag", path)
			}

			// calculate directory depth from base
			// depth := strings.Count(path[len(p):], string(filepath.Separator))

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check that the reported path and the parent path are both valid, existing paths
  2. Run the command from the project root with relative paths instead of mixed absolute paths
  3. Fix symlink/permission issues on the directories involved

Example fix

// before
found, err = fs.IsSubpathOf(p, path, baseDir)
if err != nil {
    return nil, fmt.Errorf("error checking if %s is a subpath of %s: %s", path, p, err)
}
// after — validate inputs up front
if _, err := os.Stat(baseDir); err != nil {
    return nil, fmt.Errorf("base directory %s is not accessible: %w", baseDir, err)
}
found, err = fs.IsSubpathOf(p, path, baseDir)
if err != nil {
    return nil, fmt.Errorf("error checking if %s is a subpath of %s: %w", path, p, err)
}
Defensive patterns

Strategy: validation

Validate before calling

func validatePaths(paths []string, baseDir string) error {
    for _, p := range paths {
        if !filepath.IsAbs(p) && !strings.HasPrefix(p, baseDir) {
            p = filepath.Join(baseDir, p)
        }
        if _, err := os.Stat(p); err != nil {
            return fmt.Errorf("path %s invalid: %w", p, err)
        }
    }
    return nil
}

Type guard

func isUsablePath(p string) bool {
    info, err := os.Stat(p)
    return err == nil && (info.Mode().IsRegular() || info.IsDir())
}

Try / catch

resolved, err := ParseInputPaths(raw, baseDir, params)
if err != nil {
    if strings.Contains(err.Error(), "is a subpath of") {
        fmt.Printf("bad path argument: %v\n", err)
        os.Exit(2)
    }
    return err
}

Prevention

When it happens

Trigger: fs.IsSubpathOf(p, path, baseDir) returns an error while iterating fileOrDirPaths — usually on invalid path strings, unreadable directories needing evaluation, or malformed relative/absolute mixes.

Common situations: Passing a path containing invalid characters or NUL bytes; baseDir no longer existing (deleted working directory); symlinks that cannot be resolved due to permissions.

Related errors


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