router-for-me/CLIProxyAPI · error
artifact not found for %s/%s
Error message
artifact not found for %s/%s
What it means
SelectArtifact iterates the plan's normalized artifact list looking for one whose GOOS and GOARCH match the supplied values. It throws 'artifact not found for %s/%s' when no artifact entry covers the caller's platform pair (e.g. linux/arm64). Both inputs are normalized first, so the error text shows the canonical GOOS/GOARCH that failed to match.
Source
Thrown at internal/pluginstore/direct.go:23
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
)
func SelectArtifact(plan InstallPlan, goos string, goarch string) (Artifact, error) {
plan = NormalizeInstallPlan(plan)
goos = normalizeGOOS(goos)
goarch = normalizeGOARCH(goarch)
if plan.Type != InstallTypeDirect {
return Artifact{}, fmt.Errorf("install type %q is not direct", plan.Type)
}
for _, artifact := range plan.Artifacts {
if artifact.GOOS == goos && artifact.GOARCH == goarch {
return artifact, nil
}
}
return Artifact{}, fmt.Errorf("artifact not found for %s/%s", goos, goarch)
}
func (c Client) DownloadArtifact(ctx context.Context, artifact Artifact) ([]byte, error) {
artifact = NormalizeInstallPlan(InstallPlan{Type: InstallTypeDirect, Artifacts: []Artifact{artifact}}).Artifacts[0]
if errValidate := ValidateArtifact(artifact); errValidate != nil {
return nil, errValidate
}
maxSize := int64(0)
if artifact.Size > 0 {
maxSize = artifact.Size
}
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")
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the plugin manifest's artifacts list and confirm it contains an entry for your runtime.GOOS/runtime.GOARCH.
- If you control the plugin, publish and declare a binary for the missing platform (e.g. add a linux/arm64 artifact).
- If running under emulation, pass the goos/goarch of the binary you actually want (e.g. amd64 under Rosetta) rather than the host pair.
- Fall back to a source build path for the plugin if one is available.
Example fix
// before
artifact, err := pluginstore.SelectArtifact(plan, runtime.GOOS, runtime.GOARCH)
// on linux/arm64: 'artifact not found for linux/arm64'
// after
supported := map[string]bool{}
for _, a := range plan.Artifacts {
supported[a.GOOS+"/"+a.GOARCH] = true
}
if !supported[runtime.GOOS+"/"+runtime.GOARCH] {
return fmt.Errorf("plugin does not support %s/%s; supported: %v", runtime.GOOS, runtime.GOARCH, supported)
}
artifact, err := pluginstore.SelectArtifact(plan, runtime.GOOS, runtime.GOARCH) Defensive patterns
Strategy: validation
Validate before calling
supported := map[string]bool{}
for _, a := range pluginstore.NormalizeInstallPlan(plan).Artifacts {
supported[a.GOOS+"/"+a.GOARCH] = true
}
if !supported[runtime.GOOS+"/"+runtime.GOARCH] {
return fmt.Errorf("plugin lacks %s/%s build; have %v", runtime.GOOS, runtime.GOARCH, supported)
} Type guard
func planSupports(plan pluginstore.InstallPlan, goos, goarch string) bool {
for _, a := range pluginstore.NormalizeInstallPlan(plan).Artifacts {
if a.GOOS == goos && a.GOARCH == goarch {
return true
}
}
return false
} Prevention
- Surface the supported platform list in error messages to users.
- Publish artifacts for the platforms your users run (include arm64) or provide a source fallback.
When it happens
Trigger: Calling SelectArtifact with a GOOS/GOARCH pair not present in plan.Artifacts — e.g. the plugin publishes darwin/amd64, linux/amd64, windows/amd64 but the caller runs linux/arm64; or an artifacts list that is empty after normalization.
Common situations: Installing a plugin on Apple Silicon (darwin/arm64) when the publisher only shipped amd64 builds; running on rarer platforms (freebsd, linux/386); a manifest that lists artifacts without goos/goarch fields so nothing matches; passing raw runtime values like "darwin" with an unexpected casing (normalization usually fixes this, so a genuine gap is the remaining cause).
Related errors
- install type %q is not direct
- release asset %s not found
- plugin_manifest_invalid
- plugin_install_failed
- plugin_manifest_failed
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/96dbf6382ce91adf.
Report an issue: GitHub.