siyuan-note/siyuan · error

marketplace package contains an invalid path

Error message

marketplace package contains an invalid path

What it means

A zip entry's name is empty or begins with a forward slash (absolute path). Thrown by extractLocalPackageItem (kernel/bazaar/local.go:130-132) after normalising backslashes to slashes. Absolute or empty entry names are rejected outright because they cannot map cleanly into the destination tree.

Source

Thrown at kernel/bazaar/local.go:132

		}
	}

	if err = os.MkdirAll(destination, 0755); err != nil {
		return err
	}
	var extractedTotal uint64
	for _, item := range reader.File {
		if err = extractLocalPackageItem(item, destination, &extractedTotal); err != nil {
			return err
		}
	}
	return nil
}

func extractLocalPackageItem(item *zip.File, destination string, extractedTotal *uint64) error {
	name := strings.ReplaceAll(item.Name, "\\", "/")
	if name == "" || strings.HasPrefix(name, "/") {
		return errors.New("marketplace package contains an invalid path")
	}
	destinationPath := filepath.Join(destination, filepath.FromSlash(name))
	if !gulu.File.IsSubPath(destination, destinationPath) {
		return errors.New("marketplace package contains an invalid path")
	}

	mode := item.Mode()
	if mode&os.ModeSymlink != 0 || (!mode.IsRegular() && !mode.IsDir()) {
		return errors.New("marketplace package contains an unsupported file")
	}
	if mode.IsDir() {
		return os.MkdirAll(destinationPath, 0755)
	}
	if err := os.MkdirAll(filepath.Dir(destinationPath), 0755); err != nil {
		return err
	}

	source, err := item.Open()

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Re-create the archive using relative paths (cd into the package dir before zipping)
  2. Verify entry names with `unzip -l <path>` — none should start with /
  3. If generating the zip programmatically, set zip.FileHeader.Name to a relative path

Example fix

# before: absolute paths leak into entry names
zip -r pkg.zip /home/user/myplugin

# after: zip from inside the package directory so names are relative
cd /home/user/myplugin && zip -r ../pkg.zip .
Defensive patterns

Strategy: validation

Validate before calling

func assertEntryNamesRelative(path string) error {
    r, err := zip.OpenReader(path)
    if err != nil { return err }
    defer r.Close()
    for _, f := range r.File {
        n := strings.ReplaceAll(f.Name, "\\", "/")
        if n == "" || strings.HasPrefix(n, "/") {
            return fmt.Errorf("entry name invalid: %q", f.Name)
        }
    }
    return nil
}

Try / catch

if err != nil { return fmt.Errorf("package layout invalid: %w", err) }

Prevention

When it happens

Trigger: ExtractLocalPackage decompresses an archive that contains an entry whose Name is "" or starts with "/". This typically comes from zipping with absolute paths or from a corrupt/crafted central directory.

Common situations: The author zipped files with absolute paths (e.g. `zip -r pkg.zip /home/user/...`), producing leading-slash entry names; a tool emitted a malformed entry.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/b6533392a2ebc9a1. Report an issue: GitHub.