goharbor/harbor · error · lib/errors.Error

BAD_REQUEST

BAD_REQUEST

Error message

unsupported content type: %s

What it means

While abstracting v1alpha1 annotations, Harbor pulls the layer annotated as the artifact icon, reads up to 1MB, sniffs the content type with http.DetectContentType, and accepts only GIF, PNG, or JPEG. Any other sniffed type — most commonly SVG (image/svg+xml), WEBP, BMP, ICO, or plain text — returns a BadRequest 'unsupported content type' error.

Source

Thrown at src/controller/artifact/annotation/v1alpha1.go:108

	_, icon, err := reg.PullBlob(artifact.RepositoryName, iconDigest)
	if err != nil {
		return err
	}
	defer icon.Close()
	// check the size of the size <= 1MB
	data, err := io.ReadAll(io.LimitReader(icon, 1<<20))
	if err != nil {
		if err == io.EOF {
			return errors.New(nil).WithCode(errors.BadRequestCode).WithMessage("the maximum size of the icon is 1MB")
		}
		return err
	}
	// check the content type
	contentType := http.DetectContentType(data)
	switch contentType {
	case GIF, PNG, JPEG:
	default:
		return errors.New(nil).WithCode(errors.BadRequestCode).WithMessagef("unsupported content type: %s", contentType)
	}
	artifact.Icon = iconDigest
	return nil
}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Convert the icon to PNG, GIF, or JPEG (e.g. rsvg-convert -w 256 -h 256 icon.svg -o icon.png) and re-push
  2. Keep the icon at or below 1MB or you will hit the separate size error
  3. Verify locally what Harbor will sniff: go's DetectContentType on the first 512 bytes, or file --mime-type icon.png
  4. Confirm the icon annotation actually points at the icon layer, not another layer of the artifact

Example fix

# before
file icon.svg   # icon.svg: SVG Scalable Vector Graphics image -> rejected
# after
rsvg-convert -w 256 -h 256 icon.svg -o icon.png
file icon.png   # icon.png: PNG image data -> accepted (also keep <= 1MB)
Defensive patterns

Strategy: validation

Validate before calling

// producer-side pre-check mirroring Harbor's sniff
func iconAcceptable(data []byte) bool {
    if len(data) > 1<<20 {
        return false // separate 1MB limit
    }
    switch http.DetectContentType(data) {
    case "image/gif", "image/png", "image/jpeg":
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Pushing an artifact whose layer carries the v1alpha1 icon annotation but whose bytes are SVG/WEBP/BMP/text; or the annotation pointing at the wrong layer so a non-image blob gets sniffed.

Common situations: Toolchains that annotate SVG icons exported from Figma/design tools, icon converters emitting webp, misannotated layers referencing another blob.

Related errors


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