goharbor/harbor · error · Exception
File {} should readable by owner
Error message
File {} should readable by owner What it means
MergeNativeSummary in src/pkg/scan/report/summary.go merges two report summaries for mime types whose entries in SupportedSummaryMergers point at the native merger. It type-asserts each operand to *vuln.NativeReportSummary; this instance fires when the FIRST operand s1 is not that pointer type — nil, a different struct, or a value copy.
Source
Thrown at make/photon/prepare/models.py:86
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:
# 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):View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Ensure summaries are produced by the same GenerateNativeSummary path that yields *vuln.NativeReportSummary
- Keep SupportedMimes / SupportedSummaryMergers mappings consistent for any custom mime type
- Assert the concrete type before merging and report both operand types on failure
Example fix
// before
sum, err := report.MergeNativeSummary(s1, s2) // s1 is `any`
// after
ns1, ok1 := s1.(*vuln.NativeReportSummary)
ns2, ok2 := s2.(*vuln.NativeReportSummary)
if !ok1 || !ok2 {
return nil, fmt.Errorf("cannot merge summaries: %T and %T, want *vuln.NativeReportSummary", s1, s2)
}
sum, err := report.MergeNativeSummary(ns1, ns2) Defensive patterns
Strategy: type-guard
Validate before calling
if !isNativeSummary(s1) || !isNativeSummary(s2) {
return fmt.Errorf("summary operands must be native summaries, got %T and %T", s1, s2)
} Type guard
func isNativeSummary(v any) bool {
_, ok := v.(*vuln.NativeReportSummary)
return ok
} Try / catch
if _, err := report.MergeNativeSummary(s1, s2); err != nil {
if strings.Contains(err.Error(), "native report summary required") {
log.Printf("summary mime/data mismatch: s1=%T s2=%T", s1, s2)
}
return err
} Prevention
- Generate summaries only through the registered SummaryGenerator for the mime type
- Keep summary models and mergers versioned together with the adapter
- Never hand-construct summary operands for merging
When it happens
Trigger: Summary generation after a scan merges summaries resolved from report data where s1 decoded to another type, or a caller built the summary as a value (vuln.NativeReportSummary{}) instead of a pointer.
Common situations: Custom mime registrations that resolve summaries to a different model while the merger stays native; schema drift between adapter summary output and the vuln package; passing the report object instead of its summary.
Related errors
- cert file {} should include SAN
- 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/052f087cbdf47445.
Report an issue: GitHub.