router-for-me/CLIProxyAPI · error

read %s: %w

Error message

read %s: %w

What it means

Wrapped I/O error from io.ReadAll on the opened zip entry in readTargetLibrary (install.go:360-362). The entry opened fine but reading its decompressed bytes failed — classically because the entry's declared CRC/size does not match the actual data, which archive/zip verifies at stream end. Indicates corrupted or tampered entry content.

Source

Thrown at internal/pluginstore/install.go:362

		}
		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 = 0o755
	}
	return data, mode, nil
}

func versionedPluginFileName(id string, version string, goos string) string {
	return strings.TrimSpace(id) + "-v" + normalizeVersion(version) + pluginExtension(goos)
}

func cleanZipName(name string) (string, error) {
	if strings.TrimSpace(name) == "" {
		return "", fmt.Errorf("zip entry has empty name")
	}
	if strings.Contains(name, `\`) {
		return "", fmt.Errorf("zip entry %s uses backslash path separators", name)

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Re-download the asset and retry
  2. Validate the entry independently: unzip -t artifact.zip to surface CRC errors
  3. If self-publishing, rebuild the archive and checksums together in one release job so they cannot diverge
Defensive patterns

Strategy: retry

Validate before calling

func zipCRCOK(archiveData []byte) error {
    r, err := zip.NewReader(bytes.NewReader(archiveData), int64(len(archiveData)))
    if err != nil { return err }
    for _, f := range r.File {
        rc, errOpen := f.Open()
        if errOpen != nil { return errOpen }
        _, errCopy := io.Copy(io.Discard, rc)
        rc.Close()
        if errCopy != nil { return errCopy } // surfaces CRC mismatch
    }
    return nil
}

Try / catch

if _, err := store.InstallArchive(data, plugin, opts); err != nil {
    var zipErr *zip.ChecksumError // may surface wrapped under the read error
    if errors.As(err, &zipErr) || strings.Contains(err.Error(), "read "+plugin.ID) {
        // re-download once; if it persists the asset itself is bad
    }
}

Prevention

When it happens

Trigger: InstallArchive where the target library entry's decompressed bytes fail CRC validation mid-read (zip.ErrChecksum wrapped underneath), e.g. a bit-flipped download or an asset edited after the checksums.txt was generated.

Common situations: Flaky network truncating the body, a mirrored artifact modified in transit, or a release pipeline that updates the binary inside the zip without refreshing checksums (so VerifyChecksum on the outer file passes but the inner entry is inconsistent).

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/cfc70e9d4f7b363e. Report an issue: GitHub.