siyuan-note/siyuan · error
marketplace package contains an unsupported file
Error message
marketplace package contains an unsupported file
What it means
A zip entry's mode is neither a regular file nor a directory (e.g. symlink, device, socket, named pipe). Thrown by extractLocalPackageItem (kernel/bazaar/local.go:139-141) which explicitly rejects os.ModeSymlink and any non-regular/non-dir mode. Marketplace packages may only ship regular files and directories.
Source
Thrown at kernel/bazaar/local.go:141
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()
if err != nil {
return err
}
defer source.Close()
target, err := os.OpenFile(destinationPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
written, copyErr := io.Copy(target, io.LimitReader(source, int64(maxLocalPackageFileSize)+1))View on GitHub (pinned to 251596fc0d)
Solutions
- Strip symlinks before zipping (resolve them to real files, or exclude them)
- Exclude symlink-heavy directories like node_modules, .cache, .bin from the archive
- Re-package using a tool that materializes symlinks into regular files
Example fix
# before: node_modules symlinks captured zip -r pkg.zip . -x 'node_modules/*' # (if symlinks elsewhere) zip -ry captures them as symlinks -> rejected # after: exclude symlink-heavy trees entirely zip -r pkg.zip . -x 'node_modules/*' '.pnpm-store/*' '*/.bin/*'
Defensive patterns
Strategy: validation
Validate before calling
func assertOnlyRegularAndDir(path string) error {
r, err := zip.OpenReader(path)
if err != nil { return err }
defer r.Close()
for _, f := range r.File {
m := f.Mode()
if m&os.ModeSymlink != 0 || (!m.IsRegular() && !m.IsDir()) {
return fmt.Errorf("entry %q has unsupported mode %v", f.Name, m)
}
}
return nil
} Try / catch
if err != nil { return fmt.Errorf("package contains unsupported file type: %w", err) } Prevention
- Exclude symlink-heavy trees (node_modules, .bin, .cache) before zipping
- Resolve symlinks to real files if their target is needed in the package
- Audit archive modes with `zipinfo` and strip special-file entries
When it happens
Trigger: ExtractLocalPackage encounters an entry whose zip FileHeader mode has the symlink bit set or denotes a special file type. Common when archives capture symlink-heavy trees like node_modules/.bin or .cache.
Common situations: The author zipped a directory containing symlinks (node_modules, pnpm cache, framework symlinks); a malicious archive includes device files or symlinks pointing outside the root.
Related errors
- marketplace package is too large
- marketplace package contains an invalid path
- invalid marketplace package archive
- marketplace package archive is empty
- marketplace package contains too many files
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/b494aee1017ae500.
Report an issue: GitHub.