{"record":{"id":"3d1e442078e5a63d","repo":"router-for-me/CLIProxyAPI","slug":"open-s-w","errorCode":null,"errorMessage":"open %s: %w","messagePattern":"open (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/install.go","lineNumber":353,"sourceCode":"\t\t}\n\t\tif cleanedName != targetName && cleanedName != versionedTargetName {\n\t\t\tif path.Base(cleanedName) == targetName || path.Base(cleanedName) == versionedTargetName {\n\t\t\t\treturn nil, 0, fmt.Errorf(\"target dynamic library must be at zip root\")\n\t\t\t}\n\t\t\treturn nil, 0, fmt.Errorf(\"dynamic library filename must be %s or %s\", targetName, versionedTargetName)\n\t\t}\n\t\tif target != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"zip contains multiple target dynamic libraries\")\n\t\t}\n\t\ttarget = file\n\t}\n\tif target == nil {\n\t\treturn nil, 0, fmt.Errorf(\"zip does not contain %s\", targetName)\n\t}\n\n\thandle, errOpen := target.Open()\n\tif errOpen != nil {\n\t\treturn nil, 0, fmt.Errorf(\"open %s: %w\", targetName, errOpen)\n\t}\n\tdefer func() {\n\t\tif errClose := handle.Close(); errClose != nil {\n\t\t\tlog.WithError(errClose).Debug(\"failed to close plugin archive entry\")\n\t\t}\n\t}()\n\tdata, errRead := io.ReadAll(handle)\n\tif errRead != nil {\n\t\treturn nil, 0, fmt.Errorf(\"read %s: %w\", targetName, errRead)\n\t}\n\tmode := target.FileInfo().Mode().Perm()\n\tif mode == 0 {\n\t\tmode = 0o755\n\t}\n\treturn data, mode, nil\n}\n\nfunc versionedPluginFileName(id string, version string, goos string) string {","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/install.go#L335-L371","documentation":"Wrapped I/O error from opening the selected zip entry inside readTargetLibrary (install.go:351-353). The correct entry was already located, but zip.File.Open() failed while decompressing or reading entry metadata. Because the whole archive is already in memory (zip.NewReader over archiveData), this almost always indicates corruption within the entry's stored data or headers rather than a disk problem.","triggerScenarios":"InstallArchive on an in-memory archive where the entry's compressed stream is truncated or its local header conflicts with the central directory; typically after a partially downloaded or proxy-mangled asset, or a checksum file that was regenerated for a different build so VerifyChecksum passed by coincidence of stale data.","commonSituations":"Truncated download behind a corporate proxy, a CDN serving a partial response, or a manually re-packed zip whose central directory no longer matches entry offsets.","solutions":["Re-download the artifact (clear any HTTP cache) and retry the install so a fresh, complete zip is used","Confirm the zip is well formed outside the program: unzip -t artifact.zip","If it reproduces, rebuild the release asset — the stored entry itself is corrupt"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"func zipIntact(archiveData []byte) bool {\n    r, err := zip.NewReader(bytes.NewReader(archiveData), int64(len(archiveData)))\n    if err != nil { return false }\n    for _, f := range r.File {\n        rc, errOpen := f.Open()\n        if errOpen != nil { return false }\n        _, errCopy := io.Copy(io.Discard, rc)\n        rc.Close()\n        if errCopy != nil { return false }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":"var errInstall error\nfor attempt := 0; attempt < 2; attempt++ {\n    data, _ := client.DownloadAsset(ctx, asset)\n    _, errInstall = store.InstallArchive(data, plugin, opts)\n    if errInstall == nil || !isZipIOError(errInstall) { break }\n    // re-download with cache bypassed, then retry once\n}","preventionTips":["Always run VerifyChecksum before InstallArchive (the client's Install paths do this for you)","Download via the provided Client.DownloadAsset rather than ad-hoc HTTP to keep checksum verification in the flow","Treat repeated entry-open failures as a corrupt asset: re-cut the release"],"tags":["pluginstore","zip","io","corruption"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}