router-for-me/CLIProxyAPI · critical

artifact checksum mismatch

Error message

artifact checksum mismatch

What it means

VerifyArtifactChecksum computes sha256 over the downloaded bytes and compares it (lower-cased, trimmed) to artifact.SHA256. 'artifact checksum mismatch' means the content served by the URL differs from the digest declared in the manifest. It is the direct-download integrity gate, analogous to error 600 but keyed on the artifact entry rather than a checksums map.

Source

Thrown at internal/pluginstore/direct.go:53

	data, errDownload := c.get(ctx, artifact.URL, "application/octet-stream", RequestKindArtifact, maxSize)
	if errDownload != nil {
		return nil, errDownload
	}
	if maxSize > 0 && int64(len(data)) > maxSize {
		return nil, fmt.Errorf("artifact exceeds declared size")
	}
	return data, nil
}

func VerifyArtifactChecksum(artifact Artifact, data []byte) error {
	expected := strings.ToLower(strings.TrimSpace(artifact.SHA256))
	if expected == "" {
		return fmt.Errorf("artifact checksum missing")
	}
	actualBytes := sha256.Sum256(data)
	actual := hex.EncodeToString(actualBytes[:])
	if actual != expected {
		return fmt.Errorf("artifact checksum mismatch")
	}
	return nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Re-download once to rule out transport corruption, then verify manually with sha256sum.
  2. Update the manifest's sha256 to the digest of the currently served binary (or republish the correct old binary).
  3. Pin artifact URLs to immutable, versioned release assets instead of mutable 'latest' links.
  4. Automate manifest regeneration in CI so sha256/size are recomputed on every release.

Example fix

// before
// manifest built from v1.2.3, URL later repointed to v1.3.0 binary
data, _ := client.DownloadArtifact(ctx, artifact)
err := pluginstore.VerifyArtifactChecksum(artifact, data) // mismatch

// after
// version the URL and regenerate digest on release:
//   url: https://example.com/p/1.3.0/p-linux-amd64
//   sha256: <digest of the 1.3.0 binary>
data, _ := client.DownloadArtifact(ctx, artifact)
err := pluginstore.VerifyArtifactChecksum(artifact, data)
Defensive patterns

Strategy: try-catch

Validate before calling

if strings.TrimSpace(artifact.SHA256) == "" {
    return errors.New("cannot pre-verify: manifest sha256 missing")
}

Try / catch

if err := pluginstore.VerifyArtifactChecksum(artifact, data); err != nil {
    if strings.Contains(err.Error(), "checksum mismatch") {
        // one retry with cache-bypass, then abort; never install unverified bytes
        return fmt.Errorf("integrity failure for %s: %w", artifact.Name, err)
    }
    return err
}

Prevention

When it happens

Trigger: DownloadArtifact output passed to VerifyArtifactChecksum where the digest differs: republished/rebuilt binary with a stale manifest sha256, corrupted or truncated download, or a redirect serving different content (e.g. a 'latest' URL that moved to a new build).

Common situations: Release pipeline rebuilt binaries but the plugin manifest was not regenerated; using mutable URLs (latest, /stable) instead of versioned artifact URLs; a mirror or proxy tampering with content.

Related errors


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