{"record":{"id":"cbc6e7770509ca83","repo":"goharbor/harbor","slug":"bad-request","errorCode":"BAD_REQUEST","errorMessage":"unsupported content type: %s","messagePattern":"unsupported content type: (.+?)","errorType":"error_code","errorClass":"lib/errors.Error","httpStatus":400,"severity":"error","filePath":"src/controller/artifact/annotation/v1alpha1.go","lineNumber":108,"sourceCode":"\t_, icon, err := reg.PullBlob(artifact.RepositoryName, iconDigest)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer icon.Close()\n\t// check the size of the size <= 1MB\n\tdata, err := io.ReadAll(io.LimitReader(icon, 1<<20))\n\tif err != nil {\n\t\tif err == io.EOF {\n\t\t\treturn errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(\"the maximum size of the icon is 1MB\")\n\t\t}\n\t\treturn err\n\t}\n\t// check the content type\n\tcontentType := http.DetectContentType(data)\n\tswitch contentType {\n\tcase GIF, PNG, JPEG:\n\tdefault:\n\t\treturn errors.New(nil).WithCode(errors.BadRequestCode).WithMessagef(\"unsupported content type: %s\", contentType)\n\t}\n\tartifact.Icon = iconDigest\n\treturn nil\n}\n","sourceCodeStart":90,"sourceCodeEnd":113,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/controller/artifact/annotation/v1alpha1.go#L90-L113","documentation":"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.","triggerScenarios":"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.","commonSituations":"Toolchains that annotate SVG icons exported from Figma/design tools, icon converters emitting webp, misannotated layers referencing another blob.","solutions":["Convert the icon to PNG, GIF, or JPEG (e.g. rsvg-convert -w 256 -h 256 icon.svg -o icon.png) and re-push","Keep the icon at or below 1MB or you will hit the separate size error","Verify locally what Harbor will sniff: go's DetectContentType on the first 512 bytes, or file --mime-type icon.png","Confirm the icon annotation actually points at the icon layer, not another layer of the artifact"],"exampleFix":"# before\nfile icon.svg   # icon.svg: SVG Scalable Vector Graphics image -> rejected\n# after\nrsvg-convert -w 256 -h 256 icon.svg -o icon.png\nfile icon.png   # icon.png: PNG image data -> accepted (also keep <= 1MB)","handlingStrategy":"validation","validationCode":"// producer-side pre-check mirroring Harbor's sniff\nfunc iconAcceptable(data []byte) bool {\n    if len(data) > 1<<20 {\n        return false // separate 1MB limit\n    }\n    switch http.DetectContentType(data) {\n    case \"image/gif\", \"image/png\", \"image/jpeg\":\n        return true\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use PNG icons produced by rsvg-convert or ImageMagick, not SVG or WEBP","Keep icons under 1MB","Point the icon annotation at the layer that actually contains the image bytes"],"tags":["go","harbor","artifact","icon","content-type","annotations"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}