goharbor/harbor · error · Exception
cert file {} should include SAN
Error message
cert file {} should include SAN What it means
The second assertion in MergeNativeSummary (src/pkg/scan/report/summary.go): s1 passed the *vuln.NativeReportSummary check but the SECOND operand s2 did not. Both operands must be exact *vuln.NativeReportSummary pointers for the native summary merge to proceed.
Source
Thrown at make/photon/prepare/models.py:91
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:
# pass the validation if not enabled
return
if not internal_tls_dir.exists():
raise Exception('Internal dir for tls {} not exist'.format(internal_tls_dir))
for filename in self.required_filenames:
self._check(filename)
def prepare(self):
"""
Prepare moves certs in tls file to data volume with correct permission.
"""
if not self.enabled:
logging.info('internal tls NOT enabled...')View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Validate every summary in the fold before merging; skip or fail fast on any that is not *vuln.NativeReportSummary
- Regenerate stale summaries from their reports instead of merging mixed-version data
- Log the dynamic type of the failing operand to locate the producer
Example fix
// before
sum, err := report.MergeNativeSummary(ns1, s2) // s2 is `any`
// after
ns2, ok := s2.(*vuln.NativeReportSummary)
if !ok {
return nil, fmt.Errorf("second summary is %T, want *vuln.NativeReportSummary", s2)
}
sum, err := report.MergeNativeSummary(ns1, ns2) Defensive patterns
Strategy: type-guard
Validate before calling
if !isNativeSummary(s2) {
return fmt.Errorf("second summary operand is %T, want *vuln.NativeReportSummary", s2)
} Type guard
func isNativeSummary(v any) bool {
_, ok := v.(*vuln.NativeReportSummary)
return ok
} Try / catch
sum, err := report.MergeNativeSummary(ns1, s2)
if err != nil && strings.Contains(err.Error(), "native report summary required") {
return fmt.Errorf("s2 not a native summary (%T); regenerate it from its report", s2)
} Prevention
- Validate every element in a summary fold before merging
- Regenerate stale summaries from their reports rather than merging mixed versions
- Reject nil interfaces early in reduce loops
When it happens
Trigger: Merging summaries collected from multiple scan requests where the second one was loaded from storage, a different code path, or never initialised (nil any).
Common situations: Incremental summary updates mixing old and new payload shapes; concurrent producers writing summaries with different versions of the model; nil elements in a slice being folded into one summary.
Related errors
- File {} should readable by owner
- invalid {}
- key file {} permission is not 600
- File {} not exist
- Internal dir for tls {} not exist
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/b0b1a69c5766423f.
Report an issue: GitHub.