{"record":{"id":"d41dfdbd249a1190","repo":"goharbor/harbor","slug":"not-found-d41dfd","errorCode":"NOT_FOUND","errorMessage":"the icon %s not found","messagePattern":"the icon (.+?) not found","errorType":"http","errorClass":"lib/errors.Error","httpStatus":404,"severity":"warning","filePath":"src/controller/icon/controller.go","lineNumber":149,"sourceCode":"\n\tif i, exist := builtInIcons[digest]; exist {\n\t\ticonFile, err = os.Open(i.path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer iconFile.Close()\n\t} else {\n\t\t// read icon from blob\n\t\tartifacts, err := c.artMgr.List(ctx, &q.Query{\n\t\t\tKeywords: map[string]any{\n\t\t\t\t\"Icon\": digest,\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(artifacts) == 0 {\n\t\t\treturn nil, errors.New(nil).WithCode(errors.NotFoundCode).\n\t\t\t\tWithMessagef(\"the icon %s not found\", digest)\n\t\t}\n\t\t_, iconFile, err = c.regCli.PullBlob(artifacts[0].RepositoryName, digest)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer iconFile.Close()\n\t}\n\n\timg, _, err := image.Decode(iconFile)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// resize the icon to 50x50\n\tif i, exist := builtInIcons[digest]; exist {\n\t\tif i.resize {\n\t\t\timg = resize.Thumbnail(50, 50, img, resize.NearestNeighbor)","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/controller/icon/controller.go#L131-L167","documentation":"Icon lookup first tries builtin icons, then falls back to listing artifacts whose Icon digest matches and pulling that blob from the artifact's repository. If no artifact references the digest, the controller returns NOT_FOUND 'the icon %s not found' with the digest.","triggerScenarios":"GET /api/v2/icons/{digest} where the digest belongs to a deleted artifact's icon; icon blob removed by GC after the last referencing artifact was deleted; malformed digest.","commonSituations":"UI caching an icon digest after artifacts were pruned; bookmarks/deep links to old icons; icon blob garbage-collected.","solutions":["Verify the artifact (and its icon digest) still exists via the artifact API before requesting the icon.","Re-push the artifact so its icon blob is regenerated and referenced again.","Clients should fall back to the default icon on 404 instead of surfacing an error."],"exampleFix":"// before\nicon, err := iconCtl.Get(ctx, digest)\n\n// after\nicon, err := iconCtl.Get(ctx, digest)\nif liberrors.IsErr(err, liberrors.NotFoundCode) {\n    icon, err = iconCtl.Get(ctx, defaultIconDigest)\n}","handlingStrategy":"fallback","validationCode":"// verify the artifact still carries this icon digest before fetching:\n_, err := artCtl.GetByDigest(ctx, repo, manifestDigest)\nif liberrors.IsErr(err, liberrors.NotFoundCode) { return defaultIcon() }","typeGuard":null,"tryCatchPattern":"img, err := iconCtl.Get(ctx, digest)\nif err != nil {\n    if liberrors.IsErr(err, liberrors.NotFoundCode) {\n        img = defaultIcon // graceful degradation for pruned icons\n    } else { return err }\n}","preventionTips":["Cache icons with a TTL and evict entries when their artifact is deleted.","Fall back to the default icon on 404 in UI code.","Do not persist icon digests long-term; resolve them from the artifact."],"tags":["icon","artifact","not-found","garbage-collection"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}