goharbor/harbor · error · Exception

cache expire hours should be positive number

Error message

cache expire hours should be positive number

What it means

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.

Source

Thrown at make/photon/prepare/models.py:242

        interval = self.interval[:-1]
        if not interval.isnumeric() or int(interval) < 2:
            raise Exception('purge upload interval should set with with nh, n is the number of hour and n should not beless than 2')
        return


class Cache:
    def __init__(self, config: dict):
        if not config:
            self.enabled = False
        self.enabled = config.get('enabled')
        self.expire_hours = config.get('expire_hours')

    def validate(self):
        if not self.enabled:
            return

        if not self.expire_hours or self.expire_hours <= 0:
            raise Exception('cache expire hours should be positive number')
        return

class Core:
    def __init__(self, config: dict):
        self.quota_update_provider = config.get('quota_update_provider') or 'db'

    def validate(self):
        if not self.quota_update_provider:
            return

        if self.quota_update_provider not in ['db', 'redis']:
            raise Exception('invalid quota update provider: {}'.format(self.quota_update_provider))

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Parse and validate the artifact ID at the API boundary, returning 400 for missing or invalid values
  2. Return 404 from the handler when the ID is absent rather than calling GetBy
  3. Propagate strconv errors instead of continuing with the zero value

Example fix

// before
reports, err := mgr.GetBy(ctx, artID, reg, mime, media) // artID may be 0

// after
if artID == 0 {
    return nil, errors.New("artifact id is required to fetch sbom reports")
}
reports, err := mgr.GetBy(ctx, artID, reg, mime, media)
Defensive patterns

Strategy: validation

Validate before calling

if artifactID == 0 {
    return nil, errors.New("artifact id required to fetch sbom reports")
}
return mgr.GetBy(ctx, artifactID, regUUID, mime, mediaType)

Try / catch

if _, err := mgr.GetBy(ctx, artifactID, reg, mime, media); err != nil {
    if strings.Contains(err.Error(), "no artifact id") {
        return nil, errors.New("artifact id not parsed from request path")
    }
    return nil, err
}

Prevention

When it happens

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

Common situations: URL-parameter parsing failures swallowed in handlers; events forwarded without artifact IDs; tests calling GetBy with zero values.

Related errors


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