{"record":{"id":"23bc0ad403cafc6b","repo":"slimtoolkit/slim","slug":"saving-image-index-error-s-v","errorCode":null,"errorMessage":"saving image index error - %s (%v)","messagePattern":"saving image index error - (.+?) \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/app/master/command/registry/handler_image_index.go","lineNumber":173,"sourceCode":"\timageIndex = mutate.AppendManifests(imageIndex, indexImageImgRefs...)\n\n\tif err := remote.WriteIndex(imageIndexRef, imageIndex, remoteOpts...); err != nil {\n\t\tvar terr *transport.Error\n\t\tif errors.As(err, &terr) && terr.StatusCode == http.StatusUnauthorized {\n\t\t\txc.Out.Info(\"registry.auth.error\",\n\t\t\t\tovars{\n\t\t\t\t\t\"message\": \"need to authenticate\",\n\t\t\t\t})\n\n\t\t\texitCode := -111\n\t\t\txc.Out.State(\"exited\",\n\t\t\t\tovars{\n\t\t\t\t\t\"exit.code\": exitCode,\n\t\t\t\t\t\"version\":   v.Current(),\n\t\t\t\t})\n\t\t\txc.Exit(exitCode)\n\t\t} else {\n\t\t\txc.FailOn(fmt.Errorf(\"saving image index error - %s (%v)\", cparams.ImageIndexName, err))\n\t\t}\n\t}\n\n\tindexMeta, err := remote.Index(imageIndexRef, remoteOpts...)\n\tif err != nil {\n\t\txc.FailOn(fmt.Errorf(\"index reference metadata get error - %s (%v)\", cparams.ImageIndexName, err))\n\t}\n\n\tindexMediaType, err := indexMeta.MediaType()\n\txc.FailOn(err)\n\n\tif !indexMediaType.IsIndex() {\n\t\txc.FailOn(fmt.Errorf(\"unexpected media type for index\"))\n\t}\n\n\tindexDigest, err := indexMeta.Digest()\n\txc.FailOn(err)\n","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/app/master/command/registry/handler_image_index.go#L155-L191","documentation":"The handler failed to write the assembled image index to the registry (remote.Write). When the error is not a recoverable exit-path case, it is wrapped as 'saving image index error' with the target index name and underlying error.","triggerScenarios":"remote.Write(imageIndexRef) fails during push: auth rejected (401/403), registry read-only or quota exceeded, network interruption mid-upload, blob upload rejected, or the target tag is immutable.","commonSituations":"Pushing to Docker Hub on a free plan out of pulls/storage; immutable tags enabled on the registry; proxy/firewall cutting long uploads; token expiring during large multi-arch pushes.","solutions":["Retry the push after checking network stability — blob uploads are resumable","Fix credentials/scopes so the account has push permission to the repository","Check registry quota and immutability/retention policies","Ensure the target repository exists or can be auto-created by your account"],"exampleFix":"// before\nremote.Write(imageIndexRef, imageIndex, remoteOpts...)\n// after\nremote.Write(imageIndexRef, imageIndex, append(remoteOpts,\n  remote.WithAuth(auth.FromConfig(cparams.CredsAccount, cparams.CredsSecret)))...)","handlingStrategy":"retry","validationCode":"// pre-check push permissions\nif err := checkPushAccess(registry, creds); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"err := remote.Write(imageIndexRef, imageIndex, remoteOpts...)\nif err != nil {\n    var terr *transport.Error\n    if errors.As(err, &terr) && (terr.StatusCode == 429 || terr.StatusCode >= 500 || isTransient(err)) {\n        time.Sleep(backoff)\n        err = remote.Write(imageIndexRef, imageIndex, remoteOpts...)\n    }\n    return err\n}","preventionTips":["Confirm the account has push rights and the repo isn't read-only","Watch registry quota/rate limits (especially Docker Hub)","Use stable network paths for large multi-arch pushes; avoid aggressive proxies","Retry transient failures with exponential backoff"],"tags":["network","registry","push"],"backgroundTag":"registry-push-failed","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}