{"record":{"id":"5e17075191248c2c","repo":"goharbor/harbor","slug":"nil-scan-report-object","errorCode":null,"errorMessage":"nil scan report object","messagePattern":"nil scan report object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pkg/scan/report/manager.go","lineNumber":129,"sourceCode":"// basicManager is a default implementation of report manager.\ntype basicManager struct {\n\tdao     scan.DAO\n\tvulnDao scan.VulnerabilityRecordDao\n}\n\n// NewManager news basic manager.\nfunc NewManager() Manager {\n\treturn &basicManager{\n\t\tdao:     scan.New(),\n\t\tvulnDao: scan.NewVulnerabilityRecordDao(),\n\t}\n}\n\n// Create ...\nfunc (bm *basicManager) Create(ctx context.Context, r *scan.Report) (string, error) {\n\t// Validate report object\n\tif r == nil {\n\t\treturn \"\", errors.New(\"nil scan report object\")\n\t}\n\n\tif len(r.Digest) == 0 || len(r.RegistrationUUID) == 0 || len(r.MimeType) == 0 {\n\t\treturn \"\", errors.New(\"malformed scan report object\")\n\t}\n\n\tr.UUID = uuid.New().String()\n\n\t// Insert\n\tif _, err := bm.dao.Create(ctx, r); err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn r.UUID, nil\n}\n\nfunc (bm *basicManager) Delete(ctx context.Context, uuid string) error {\n\t_, err := bm.vulnDao.DeleteForReport(ctx, uuid)","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/pkg/scan/report/manager.go#L111-L147","documentation":"Returned by basicManager.Create when the *scan.Report argument is nil. The manager validates the report object before assigning a UUID and inserting; a nil pointer is rejected immediately.","triggerScenarios":"Calling report.Mgr.Create(ctx, nil) directly; a caller unmarshaling a report from JSON into an uninitialized pointer that stays nil on error paths; nil returned by a lookup then passed straight to Create.","commonSituations":"Internal code or plugins building reports conditionally and skipping construction; error paths where an earlier unmarshal failed but the nil result was still forwarded.","solutions":["Construct the scan.Report before calling Create: set Digest, RegistrationUUID, MimeType","Check errors from any unmarshal/lookup that produces the report before passing it on","Add a nil guard at call sites to return a clearer caller-side error"],"exampleFix":"// before\nvar r *scan.Report\n_ = json.Unmarshal(data, r) // fails, r stays nil\nuuid, err := bm.Create(ctx, r)\n\n// after\nr := new(scan.Report)\nif err := json.Unmarshal(data, r); err != nil {\n    return err\n}\nuuid, err := bm.Create(ctx, r)","handlingStrategy":"type-guard","validationCode":"if r == nil {\n    return errors.New(\"cannot create a nil scan report\")\n}\nuuid, err := bm.Create(ctx, r)","typeGuard":"func isReportReadyForCreate(r *scan.Report) bool {\n    return r != nil\n}","tryCatchPattern":null,"preventionTips":["Always construct the struct (new(scan.Report)) before filling it","Check unmarshal errors before reusing the target pointer","Static-analyze for nil-deref paths into Create"],"tags":["scan","report","nil-check","validation"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}