goharbor/harbor · error
malformed scan report object
Error message
malformed scan report object
What it means
Returned by basicManager.Create when the report is non-nil but one of Digest, RegistrationUUID, or MimeType is empty. These three fields are the minimum identity of a scan report (what artifact, scanned by which scanner, in which format); without them the row cannot be inserted meaningfully.
Source
Thrown at src/pkg/scan/report/manager.go:133
}
// NewManager news basic manager.
func NewManager() Manager {
return &basicManager{
dao: scan.New(),
vulnDao: scan.NewVulnerabilityRecordDao(),
}
}
// Create ...
func (bm *basicManager) Create(ctx context.Context, r *scan.Report) (string, error) {
// Validate report object
if r == nil {
return "", errors.New("nil scan report object")
}
if len(r.Digest) == 0 || len(r.RegistrationUUID) == 0 || len(r.MimeType) == 0 {
return "", errors.New("malformed scan report object")
}
r.UUID = uuid.New().String()
// Insert
if _, err := bm.dao.Create(ctx, r); err != nil {
return "", err
}
return r.UUID, nil
}
func (bm *basicManager) Delete(ctx context.Context, uuid string) error {
_, err := bm.vulnDao.DeleteForReport(ctx, uuid)
if err != nil {
return err
}
query := q.Query{Keywords: q.KeyWords{"uuid": uuid}}View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Populate all three required fields before Create: Digest (sha256:...), RegistrationUUID (from the scanner registration), MimeType (e.g. application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0)
- Log the offending struct right before Create to see which field is blank
- Validate at the API boundary and return BAD_REQUEST with field details
Example fix
// before
r := &scan.Report{Digest: dgst}
uuid, err := bm.Create(ctx, r)
// after
r := &scan.Report{
Digest: dgst,
RegistrationUUID: reg.UUID,
MimeType: v1.MimeTypeNativeReport,
}
uuid, err := bm.Create(ctx, r) Defensive patterns
Strategy: validation
Validate before calling
if r == nil || len(r.Digest) == 0 || len(r.RegistrationUUID) == 0 || len(r.MimeType) == 0 {
return errors.New("report needs digest, registration UUID and mime type")
}
uuid, err := bm.Create(ctx, r) Type guard
func isReportComplete(r *scan.Report) bool {
return r != nil &&
len(r.Digest) > 0 &&
len(r.RegistrationUUID) > 0 &&
len(r.MimeType) > 0
} Prevention
- Build reports from a constructor that requires the three fields
- Reject at the API boundary with per-field 400 details
- Log the struct contents when validation fails to spot the blank field fast
When it happens
Trigger: Creating a report from a partially populated struct, e.g. digest set but registration UUID missing because the scanner lookup failed silently; requests arriving without mime type after mime negotiation; code that fills fields conditionally.
Common situations: On-demand scan API handlers losing the registration context; adapters that do not report a mime type; refactors that rename fields and leave the old ones empty.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- File {} not exist
- Internal dir for tls {} not exist
- nil scan report object
- empty digest to get report data
- missing uuid
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/d9d1cc9db9c13bd0.
Report an issue: GitHub.