goharbor/harbor · warning · lib/errors.Error

NOT_FOUND

NOT_FOUND

Error message

the icon %s not found

What it means

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.

Source

Thrown at src/controller/icon/controller.go:149

	if i, exist := builtInIcons[digest]; exist {
		iconFile, err = os.Open(i.path)
		if err != nil {
			return nil, err
		}
		defer iconFile.Close()
	} else {
		// read icon from blob
		artifacts, err := c.artMgr.List(ctx, &q.Query{
			Keywords: map[string]any{
				"Icon": digest,
			},
		})
		if err != nil {
			return nil, err
		}
		if len(artifacts) == 0 {
			return nil, errors.New(nil).WithCode(errors.NotFoundCode).
				WithMessagef("the icon %s not found", digest)
		}
		_, iconFile, err = c.regCli.PullBlob(artifacts[0].RepositoryName, digest)
		if err != nil {
			return nil, err
		}
		defer iconFile.Close()
	}

	img, _, err := image.Decode(iconFile)
	if err != nil {
		return nil, err
	}

	// resize the icon to 50x50
	if i, exist := builtInIcons[digest]; exist {
		if i.resize {
			img = resize.Thumbnail(50, 50, img, resize.NearestNeighbor)

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Verify the artifact (and its icon digest) still exists via the artifact API before requesting the icon.
  2. Re-push the artifact so its icon blob is regenerated and referenced again.
  3. Clients should fall back to the default icon on 404 instead of surfacing an error.

Example fix

// before
icon, err := iconCtl.Get(ctx, digest)

// after
icon, err := iconCtl.Get(ctx, digest)
if liberrors.IsErr(err, liberrors.NotFoundCode) {
    icon, err = iconCtl.Get(ctx, defaultIconDigest)
}
Defensive patterns

Strategy: fallback

Validate before calling

// verify the artifact still carries this icon digest before fetching:
_, err := artCtl.GetByDigest(ctx, repo, manifestDigest)
if liberrors.IsErr(err, liberrors.NotFoundCode) { return defaultIcon() }

Try / catch

img, err := iconCtl.Get(ctx, digest)
if err != nil {
    if liberrors.IsErr(err, liberrors.NotFoundCode) {
        img = defaultIcon // graceful degradation for pruned icons
    } else { return err }
}

Prevention

When it happens

Trigger: 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.

Common situations: UI caching an icon digest after artifacts were pruned; bookmarks/deep links to old icons; icon blob garbage-collected.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/d41dfdbd249a1190. Report an issue: GitHub.