vxcontrol/pentagi · error

invalid path

Error message

invalid path

What it means

SanitizeResourcePath returns this when, after cleaning, the resulting relative path is empty or '.' — i.e. the input named no actual file (it was '.', './', '././', or reduced to nothing). It then validates each component via validatePathComponent, so this specific message means the path as a whole carried no content.

Source

Thrown at backend/pkg/resources/resources.go:158

	}
	if len(trimmed) > MaxPathLength {
		return "", fmt.Errorf("path exceeds maximum allowed length of %d characters", MaxPathLength)
	}

	normalized := strings.ReplaceAll(trimmed, "\\", "/")
	if strings.HasPrefix(normalized, "/") {
		return "", fmt.Errorf("path must be relative")
	}
	for _, part := range strings.Split(normalized, "/") {
		if part == ".." {
			return "", fmt.Errorf("path must not contain parent directory traversal")
		}
	}
	cleaned := path.Clean("/" + normalized)
	// Remove the leading "/" we added for Clean, making the path relative.
	rel := strings.TrimPrefix(cleaned, "/")
	if rel == "" || rel == "." {
		return "", fmt.Errorf("invalid path")
	}

	// Validate every path component.
	parts := strings.Split(rel, "/")
	for _, part := range parts {
		if err := validatePathComponent(part); err != nil {
			return "", err
		}
	}

	return rel, nil
}

// SanitizeResourceDir is like SanitizeResourcePath but also accepts an empty
// string to mean "root". It returns "" for root, or a clean relative path.
func SanitizeResourceDir(p string) (string, error) {
	if strings.TrimSpace(p) == "" {
		return "", nil

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check that the input names an actual file before calling the API (non-empty basename after trimming)
  2. Reject "." and empty strings at your entry point with a clearer message
  3. Use SanitizeResourceFileName when you expect a bare filename, which produces a clearer 'file name is required' error
  4. Trace where the value came from — usually a TrimPrefix or path.Dir call that removed too much

Example fix

// before
name, err := resources.SanitizeResourcePath("./")
// after
base := path.Base(strings.TrimSpace(input))
if base == "." || base == "/" {
    return fmt.Errorf("a file name is required, got %q", input)
}
name, err := resources.SanitizeResourcePath(input)
Defensive patterns

Strategy: validation

Validate before calling

func isMeaningfulPath(p string) bool {
	trimmed := strings.TrimSpace(p)
	cleaned := path.Clean("/" + strings.ReplaceAll(trimmed, "\\", "/"))
	rel := strings.TrimPrefix(cleaned, "/")
	return rel != "" && rel != "."
}

Try / catch

name, err := resources.SanitizeResourcePath(input)
if err != nil {
	if strings.Contains(err.Error(), "invalid path") {
		return fmt.Errorf("path %q does not name a file", input)
	}
	return err
}

Prevention

When it happens

Trigger: Calling SanitizeResourcePath with ".", "./", "", or a string of only slashes/dots that path.Clean collapses to the root; also hit when a caller strips a prefix and nothing remains.

Common situations: Off-by-one string trimming that consumes the filename; a client sending a directory path instead of a file; an empty form field that passed a weaker upstream check.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/46f6a7588386fb9d. Report an issue: GitHub.