{"record":{"id":"89c9b37200aae162","repo":"router-for-me/CLIProxyAPI","slug":"artifact-exceeds-declared-size","errorCode":null,"errorMessage":"artifact exceeds declared size","messagePattern":"artifact exceeds declared size","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"internal/pluginstore/direct.go","lineNumber":40,"sourceCode":"\t}\n\treturn Artifact{}, fmt.Errorf(\"artifact not found for %s/%s\", goos, goarch)\n}\n\nfunc (c Client) DownloadArtifact(ctx context.Context, artifact Artifact) ([]byte, error) {\n\tartifact = NormalizeInstallPlan(InstallPlan{Type: InstallTypeDirect, Artifacts: []Artifact{artifact}}).Artifacts[0]\n\tif errValidate := ValidateArtifact(artifact); errValidate != nil {\n\t\treturn nil, errValidate\n\t}\n\tmaxSize := int64(0)\n\tif artifact.Size > 0 {\n\t\tmaxSize = artifact.Size\n\t}\n\tdata, errDownload := c.get(ctx, artifact.URL, \"application/octet-stream\", RequestKindArtifact, maxSize)\n\tif errDownload != nil {\n\t\treturn nil, errDownload\n\t}\n\tif maxSize > 0 && int64(len(data)) > maxSize {\n\t\treturn nil, fmt.Errorf(\"artifact exceeds declared size\")\n\t}\n\treturn data, nil\n}\n\nfunc VerifyArtifactChecksum(artifact Artifact, data []byte) error {\n\texpected := strings.ToLower(strings.TrimSpace(artifact.SHA256))\n\tif expected == \"\" {\n\t\treturn fmt.Errorf(\"artifact checksum missing\")\n\t}\n\tactualBytes := sha256.Sum256(data)\n\tactual := hex.EncodeToString(actualBytes[:])\n\tif actual != expected {\n\t\treturn fmt.Errorf(\"artifact checksum mismatch\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":22,"sourceCodeEnd":57,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/direct.go#L22-L57","documentation":"Client.DownloadArtifact enforces the artifact's declared Size as a cap: it passes maxSize to the HTTP getter (which limits the read) and then re-checks that len(data) does not exceed it. 'artifact exceeds declared size' means the downloaded payload was larger than the size published in the plugin manifest — the download is rejected rather than trusted.","triggerScenarios":"DownloadArtifact succeeds at the HTTP layer but returns more bytes than artifact.Size (only possible when Size > 0). Typically the server ignored the Range/limit semantics, the manifest's size field is stale, or the URL was redirected to a larger file (e.g. an HTML sign-in page or a newer build).","commonSituations":"Manifest size field not regenerated after a plugin rebuild; a proxy or artifact registry wrapping the binary (adding headers/HTML); downloading from a URL that now serves a different, larger asset.","solutions":["Refresh the plugin index/manifest so artifact.Size matches the currently published binary.","If you publish the plugin, regenerate the manifest (size + sha256) on every release.","Check what the URL actually serves (curl -L the artifact URL and compare Content-Length) to spot redirect/wrapping issues.","Remove a stale zero/wrong Size only if you are certain the size is unknown — note Size == 0 disables the cap entirely."],"exampleFix":"// before\n// manifest stale: size: 1200000 but binary is now 1350000 bytes\nartifact, data, err := fetchAndDownload(plan) // 'artifact exceeds declared size'\n\n// after\n// regenerate manifest from the actual release assets:\n//   size: 1350000\n//   sha256: <new digest>\nartifact, data, err := fetchAndDownload(plan)","handlingStrategy":"validation","validationCode":"if artifact.Size > 0 {\n    log.Debugf(\"expecting ~%d bytes for %s\", artifact.Size, artifact.Name)\n}","typeGuard":null,"tryCatchPattern":"data, err := client.DownloadArtifact(ctx, artifact)\nif err != nil {\n    if strings.Contains(err.Error(), \"exceeds declared size\") {\n        return fmt.Errorf(\"manifest is stale for %s — refresh the plugin index\", artifact.Name)\n    }\n    return err\n}","preventionTips":["Regenerate size and sha256 together in the release pipeline.","Treat a size overrun the same as a checksum mismatch: suspect, not tolerate."],"tags":["size-limit","download","manifest","plugin-store"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}