goharbor/harbor · error · Exception
invalid {}
Error message
invalid {} What it means
MergeNativeReport in src/pkg/scan/report/report.go is the merger bound to the native vulnerability mime types (v1.MimeTypeNativeReport and v1.MimeTypeGenericVulnerabilityReport in SupportedMergers). It type-asserts each operand to *vuln.Report; this instance fires when the FIRST operand r1 is not a *vuln.Report pointer — it may be nil, a different model, or a vuln.Report taken by value.
Source
Thrown at make/photon/prepare/models.py:76
if filename in self.required_filenames:
return os.path.join(self.data_volume, 'secret', 'tls', filename)
return object.__getattribute__(self, name)
def _check(self, filename: str):
"""
Check cert and key files are correct
"""
path = Path(os.path.join(internal_tls_dir, filename))
if not path.exists:
if filename == 'harbor_internal_ca.crt':
return
raise Exception('File {} not exist'.format(filename))
if not path.is_file:
raise Exception('invalid {}'.format(filename))
# check key file permission
if filename.endswith('.key') and not check_permission(path, mode=0o600):
raise Exception('key file {} permission is not 600'.format(filename))
# check certificate file
if filename.endswith('.crt'):
if not owner_can_read(path.stat().st_mode):
# check owner can read cert file
raise Exception('File {} should readable by owner'.format(filename))
if not san_existed(path):
# check SAN included
if filename == 'harbor_internal_ca.crt':
return
raise Exception('cert file {} should include SAN'.format(filename))
def validate(self):
if not self.enabled:View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Ensure both operands are *vuln.Report pointers produced by the same ResolveData path used for the merge
- Check the SupportedMimes entry for the mime type in play — the model it resolves must match the merger registered in SupportedMergers
- Align scanner adapter and Harbor versions so reports decode into the native model
Example fix
// before
merged, err := report.MergeNativeReport(r1, r2) // r1, r2 are `any`
// after
nr1, ok1 := r1.(*vuln.Report)
nr2, ok2 := r2.(*vuln.Report)
if !ok1 || !ok2 {
return nil, fmt.Errorf("cannot merge: operands are %T and %T, want *vuln.Report", r1, r2)
}
merged, err := report.MergeNativeReport(nr1, nr2) Defensive patterns
Strategy: type-guard
Validate before calling
if !isNativeReport(r1) || !isNativeReport(r2) {
return fmt.Errorf("merge operands must be native reports, got %T and %T", r1, r2)
} Type guard
func isNativeReport(v any) bool {
_, ok := v.(*vuln.Report)
return ok
} Try / catch
if _, err := report.MergeNativeReport(r1, r2); err != nil {
if strings.Contains(err.Error(), "native report required") {
log.Printf("mime/data mismatch in merge: r1=%T r2=%T", r1, r2) // inspect SupportedMimes mapping
}
return err
} Prevention
- Keep mime-to-model (SupportedMimes) and mime-to-merger (SupportedMergers) maps consistent for any custom mime
- Always merge values produced by ResolveData, not hand-built ones
- Log %T of operands when a merge fails to catch value-vs-pointer mistakes
When it happens
Trigger: Reports.ResolveData(mimeType) selecting MergeNativeReport while the decoded first report resolved to another type — e.g. SupportedMimes maps the mime to a non-native model, or a caller merged values instead of pointers.
Common situations: Registering a custom mime type in SupportedMimes without also binding a matching merger in SupportedMergers; version skew between the adapter's report schema and the Harbor vuln package; passing vuln.Report{} instead of &vuln.Report{}.
Related errors
- key file {} permission is not 600
- File {} should readable by owner
- cert file {} should include SAN
- File {} not exist
- Internal dir for tls {} not exist
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/aa09ea0194b35a99.
Report an issue: GitHub.