router-for-me/CLIProxyAPI · error
zip does not contain %s
Error message
zip does not contain %s
What it means
Thrown by readTargetLibrary in internal/pluginstore/install.go when the archive zip was parsed successfully but no entry matches the expected dynamic library filename. The expected name is derived from the plugin id, GOOS extension (install.go:319-320): <id>.so/.dylib/.dll or <id>-v<version><ext>. All entries lacking a dynamic library extension are skipped, so an archive of only READMEs or a misnamed binary yields this error.
Source
Thrown at internal/pluginstore/install.go:348
if !regularZipFile(file) {
return nil, 0, fmt.Errorf("zip entry %s is not a regular file", file.Name)
}
if !hasDynamicLibraryExtension(cleanedName) {
continue
}
if cleanedName != targetName && cleanedName != versionedTargetName {
if path.Base(cleanedName) == targetName || path.Base(cleanedName) == versionedTargetName {
return nil, 0, fmt.Errorf("target dynamic library must be at zip root")
}
return nil, 0, fmt.Errorf("dynamic library filename must be %s or %s", targetName, versionedTargetName)
}
if target != nil {
return nil, 0, fmt.Errorf("zip contains multiple target dynamic libraries")
}
target = file
}
if target == nil {
return nil, 0, fmt.Errorf("zip does not contain %s", targetName)
}
handle, errOpen := target.Open()
if errOpen != nil {
return nil, 0, fmt.Errorf("open %s: %w", targetName, errOpen)
}
defer func() {
if errClose := handle.Close(); errClose != nil {
log.WithError(errClose).Debug("failed to close plugin archive entry")
}
}()
data, errRead := io.ReadAll(handle)
if errRead != nil {
return nil, 0, fmt.Errorf("read %s: %w", targetName, errRead)
}
mode := target.FileInfo().Mode().Perm()
if mode == 0 {
mode = 0o755View on GitHub (pinned to 78f0c4079e)
Solutions
- Verify the zip actually contains <id><ext> or <id>-v<version><ext> at the root: unzip -l artifact.zip
- Align options.GOOS with the platform the asset was built for (the asset selection uses the same GOOS/GOARCH)
- Fix the release packaging to rename the built library to the plugin id plus the correct extension before zipping
Defensive patterns
Strategy: validation
Validate before calling
func hasTargetLib(archiveData []byte, id, version, goos string) bool {
r, err := zip.NewReader(bytes.NewReader(archiveData), int64(len(archiveData)))
if err != nil { return false }
ext := map[string]string{"darwin": ".dylib", "windows": ".dll"}[goos]
if ext == "" { ext = ".so" }
want := map[string]bool{id + ext: true, id + "-v" + version + ext: true}
for _, f := range r.File {
if want[path.Clean(f.Name)] { return true }
}
return false
} Try / catch
if err := installAndLog(data, plugin, opts); err != nil {
if strings.Contains(err.Error(), "zip does not contain") {
log.Errorf("artifact for %s/%s lacks the expected library; check asset naming", opts.GOOS, opts.GOARCH)
}
} Prevention
- Name the built library exactly as the plugin id with the platform extension before zipping
- Test-install each release asset for every GOOS/GOARCH you publish in CI
- Confirm options.GOOS matches the asset you downloaded (asset selection and zip scanning use the same value)
When it happens
Trigger: InstallArchive or any Client.Install* path where the downloaded zip contains the library under a different name (e.g. 'libmyplugin.so' or 'plugin.bin'), targets a different OS extension than options.GOOS implies (a .dll in the zip while GOOS=linux expects .so), or the library sits in a subdirectory with a non-matching base name.
Common situations: Release assets built for one platform installed with another GOOS; plugin id in the registry not matching the binary name inside the artifact; an archive that ships source or docs instead of the compiled library because the release job skipped the build step.
Related errors
- zip contains multiple target dynamic libraries
- plugin_update_requires_restart
- target dynamic library must be at zip root
- dynamic library filename must be %s or %s
- open %s: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/ab2fbb0214e566fe.
Report an issue: GitHub.