vxcontrol/pentagi · error

path must not be empty

Error message

path must not be empty

What it means

SanitizeResourcePath (resources.go:139) normalizes client-supplied virtual paths and rejects the empty string before any other checks. The error 'path must not be empty' means the input, after strings.TrimSpace, had length zero. It guards Resources, SanitizeResourceDir, ZipResources, AddResourceFromFlow and friends from building blob paths from blank names.

Source

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

	}
	err := os.Remove(BlobPath(dataDir, hash))
	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to delete blob %s: %w", hash, err)
	}
	return nil
}

// SanitizeResourcePath normalises a client-supplied virtual path and ensures it
// is safe to use:
//   - trims whitespace
//   - converts backslashes to forward slashes
//   - cleans the path (removes .., double slashes, etc.)
//   - rejects absolute paths, dot-only components, and paths that exceed MaxPathLength
//   - returns an error for the empty path
func SanitizeResourcePath(p string) (string, error) {
	trimmed := strings.TrimSpace(p)
	if trimmed == "" {
		return "", fmt.Errorf("path must not be empty")
	}
	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 == "." {

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check the string is non-empty after trimming before calling any resource API
  2. For optional fields, substitute a default path (e.g. "uploads/file.bin") or skip the entry and log it
  3. Validate incoming API payloads with a schema (zod/gozod, JSON schema) requiring non-empty path
  4. Trace which caller produced the empty value (Resources, AddResourceFromFlow, etc.) and fix the data source

Example fix

// before
sanitized, err := resources.SanitizeResourcePath(req.Path) // req.Path may be ""
// after
p := strings.TrimSpace(req.Path)
if p == "" { return fmt.Errorf("resource path required") }
sanitized, err := resources.SanitizeResourcePath(p)
Defensive patterns

Strategy: validation

Validate before calling

func nonEmptyPath(p string) bool { return strings.TrimSpace(p) != "" }
// guard: if !nonEmptyPath(req.Path) { return errors.New("path is required") }

Type guard

func hasResourcePath(p *string) bool { return p != nil && strings.TrimSpace(*p) != "" }

Try / catch

sanitized, err := resources.SanitizeResourcePath(p)
if err != nil {
    if strings.Contains(err.Error(), "path must not be empty") {
        return fmt.Errorf("client error: missing resource path")
    }
    return err
}

Prevention

When it happens

Trigger: Calling SanitizeResourcePath("") or with a whitespace-only string like " ", or passing an unset/zero-value variable; callers such as AddResourceFromFlow or collectAndSanitizeResourcePaths forwarding empty optional path fields from API payloads.

Common situations: JSON requests omitting an optional 'path' field which arrives as ""; database rows with empty path columns; shell scripts passing unquoted empty variables; form submissions where the user left the path input blank.

Related errors


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