{"record":{"id":"07622090c2d5ec69","repo":"goharbor/harbor","slug":"cache-expire-hours-should-be-positive-number","errorCode":null,"errorMessage":"cache expire hours should be positive number","messagePattern":"cache expire hours should be positive number","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/models.py","lineNumber":242,"sourceCode":"        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\nclass Core:\n    def __init__(self, config: dict):\n        self.quota_update_provider = config.get('quota_update_provider') or 'db'\n\n    def validate(self):\n        if not self.quota_update_provider:\n            return\n\n        if self.quota_update_provider not in ['db', 'redis']:\n            raise Exception('invalid quota update provider: {}'.format(self.quota_update_provider))","sourceCodeStart":224,"sourceCodeEnd":254,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/models.py#L224-L254","documentation":"SBOM report manager GetBy requires a non-zero artifact ID as the mandatory lookup key; artifactID == 0 returns 'no artifact id to get sbom report data' before any query keywords are built. The other filter parameters (registration uuid, mime, media type) are optional narrowing filters.","triggerScenarios":"GetBy(ctx, 0, regUUID, mime, media) — the artifact ID from the API path or event was never parsed, e.g. a strconv.Atoi error was ignored and the value defaulted to 0.","commonSituations":"URL-parameter parsing failures swallowed in handlers; events forwarded without artifact IDs; tests calling GetBy with zero values.","solutions":["Parse and validate the artifact ID at the API boundary, returning 400 for missing or invalid values","Return 404 from the handler when the ID is absent rather than calling GetBy","Propagate strconv errors instead of continuing with the zero value"],"exampleFix":"// before\nreports, err := mgr.GetBy(ctx, artID, reg, mime, media) // artID may be 0\n\n// after\nif artID == 0 {\n    return nil, errors.New(\"artifact id is required to fetch sbom reports\")\n}\nreports, err := mgr.GetBy(ctx, artID, reg, mime, media)","handlingStrategy":"validation","validationCode":"if artifactID == 0 {\n    return nil, errors.New(\"artifact id required to fetch sbom reports\")\n}\nreturn mgr.GetBy(ctx, artifactID, regUUID, mime, mediaType)","typeGuard":null,"tryCatchPattern":"if _, err := mgr.GetBy(ctx, artifactID, reg, mime, media); err != nil {\n    if strings.Contains(err.Error(), \"no artifact id\") {\n        return nil, errors.New(\"artifact id not parsed from request path\")\n    }\n    return nil, err\n}","preventionTips":["Parse path parameters with error propagation","Return 400 at the handler when the artifact id is missing","Add contract tests for handlers with empty id parameters"],"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"}