{"record":{"id":"1dc5faf173e612de","repo":"goharbor/harbor","slug":"purge-upload-interval-should-set-with-with-nh-n-i-1dc5fa","errorCode":null,"errorMessage":"purge upload interval should set with with nh, n is the number of hour and n should not beless than 2","messagePattern":"purge upload interval should set with with nh, n is the number of hour and n should not beless than 2","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/models.py","lineNumber":226,"sourceCode":"\n    def validate(self):\n        if not self.enabled:\n            return\n        # age should end with h\n        if not isinstance(self.age, str) or not self.age.endswith('h'):\n            raise Exception('purge upload age should set with with nh, n is the number of hour')\n        # interval should larger than 2h\n        age = self.age[:-1]\n        if not age.isnumeric() or int(age) < 2:\n            raise Exception('purge upload age should set with with nh, n is the number of hour and n should not be less than 2')\n\n        # interval should end with h\n        if not isinstance(self.interval, str) or not self.interval.endswith('h'):\n            raise Exception('purge upload interval should set with with nh, n is the number of hour')\n        # interval should larger than 2h\n        interval = self.interval[:-1]\n        if not interval.isnumeric() or int(interval) < 2:\n            raise Exception('purge upload interval should set with with nh, n is the number of hour and n should not beless than 2')\n        return\n\n\nclass Cache:\n    def __init__(self, config: dict):\n        if not config:\n            self.enabled = False\n        self.enabled = config.get('enabled')\n        self.expire_hours = config.get('expire_hours')\n\n    def validate(self):\n        if not self.enabled:\n            return\n\n        if not self.expire_hours or self.expire_hours <= 0:\n            raise Exception('cache expire hours should be positive number')\n        return\n","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/models.py#L208-L244","documentation":"The field-level check in SBOM manager Create: a non-nil report must carry a non-zero ArtifactID plus non-empty RegistrationUUID, MimeType and MediaType. Missing any one returns 'malformed sbom report object' before the UUID is generated and the row inserted.","triggerScenarios":"Creating a model.Report whose artifact_id is 0 because the artifact lookup failed silently, or whose registration uuid, mime type or media type strings were never filled.","commonSituations":"SBOM ingest code resolving artifact IDs from events that lack them; forgetting MediaType when porting code from the vulnerability report manager (which does not require it); registration UUID not threaded from the scanner registration.","solutions":["Resolve the artifact ID before building the report and fail clearly if the artifact is not found","Fill registration_uuid from the scanner registration and mime/media types from the SBOM content","Validate the fields where they are produced, not only inside the manager"],"exampleFix":"// before\nr := &model.Report{\n    ArtifactID: artID, // may be 0\n    MimeType:  mime,\n}\nid, err := mgr.Create(ctx, r)\n\n// after\nif artID == 0 || regUUID == \"\" || mime == \"\" || mediaType == \"\" {\n    return \"\", fmt.Errorf(\"incomplete sbom report: artifact=%d reg=%q mime=%q media=%q\", artID, regUUID, mime, mediaType)\n}\nr := &model.Report{ArtifactID: artID, RegistrationUUID: regUUID, MimeType: mime, MediaType: mediaType}\nid, err := mgr.Create(ctx, r)","handlingStrategy":"validation","validationCode":"if r == nil || r.ArtifactID == 0 || r.RegistrationUUID == \"\" || r.MimeType == \"\" || r.MediaType == \"\" {\n    return fmt.Errorf(\"incomplete sbom report: artifact=%d reg=%q mime=%q media=%q\",\n        r.GetArtifactID(), r.RegistrationUUID, r.MimeType, r.MediaType)\n}\nreturn mgr.Create(ctx, r)","typeGuard":null,"tryCatchPattern":"if _, err := mgr.Create(ctx, r); err != nil {\n    if strings.Contains(err.Error(), \"malformed sbom report object\") {\n        return errors.New(\"sbom report needs artifact id, registration uuid, mime and media type\")\n    }\n    return err\n}","preventionTips":["Resolve the artifact ID before building the report","Note MediaType is mandatory here but not in the vulnerability report manager","Fill registration uuid from the scanner registration, not from request payloads"],"tags":["go","harbor","sbom","report","validation"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}