goharbor/harbor · error · Exception
Cert File {} should be owned by user with uid 10000 or reada
Error message
Cert File {} should be owned by user with uid 10000 or readable by others What it means
Thrown by validate() in make/photon/prepare/utils/configs.py when the registry custom CA bundle is owned by uid 10000 (DEFAULT_UID, Harbor's runtime user) but the owner-read permission bit is missing (owner_can_read(st_mode) is false). A file owned by the Harbor uid that it cannot read is treated as a misconfiguration and blocks prepare, since registry/core would fail to load it.
Source
Thrown at make/photon/prepare/utils/configs.py:73
if storage_provider_config == "":
raise Exception(
"Error: no provider configurations are provided for provider %s" % storage_provider_name)
# ca_bundle validate
if conf.get('registry_custom_ca_bundle_path'):
registry_custom_ca_bundle_path = conf.get('registry_custom_ca_bundle_path') or ''
if registry_custom_ca_bundle_path.startswith('/data/'):
ca_bundle_host_path = registry_custom_ca_bundle_path
else:
ca_bundle_host_path = os.path.join(host_root_dir, registry_custom_ca_bundle_path.lstrip('/'))
try:
uid = os.stat(ca_bundle_host_path).st_uid
st_mode = os.stat(ca_bundle_host_path).st_mode
except Exception as e:
logging.error(e)
raise Exception('Can not get file info')
err_msg = 'Cert File {} should be owned by user with uid 10000 or readable by others'.format(registry_custom_ca_bundle_path)
if uid == DEFAULT_UID and not owner_can_read(st_mode):
raise Exception(err_msg)
if uid != DEFAULT_UID and not other_can_read(st_mode):
raise Exception(err_msg)
# TODO:
# If user enable trust cert dir, need check if the files in this dir is readable.
if conf.get('trace'):
conf['trace'].validate()
if conf.get('purge_upload'):
conf['purge_upload'].validate()
if conf.get('cache'):
conf['cache'].validate()
if conf.get('core'):
conf['core'].validate()
View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Restore the owner-read bit: chmod u+r <ca_bundle> (or chmod 0400/0444)
- Confirm with: stat -c '%u %a' <ca_bundle> # expect 10000 and a mode with owner r
- Re-run ./install.sh
- If the file is deliberately root-owned, see the sibling check (error 30) and make it world-readable instead
Example fix
# on the Harbor host (before) $ stat -c '%u %a' /data/secret/root-ca.pem 10000 200 # after $ chmod 0400 /data/secret/root-ca.pem $ stat -c '%u %a' /data/secret/root-ca.pem 10000 400
Defensive patterns
Strategy: validation
Validate before calling
import os, stat as st
p = cfg.get('storage_service', {}).get('ca_bundle')
if p and os.path.isfile(p):
s = os.stat(p)
if s.st_uid == 10000 and not (s.st_mode & st.S_IRUSR):
raise SystemExit('ca_bundle owned by 10000 lacks owner read: chmod u+r %s' % p) Prevention
- After chowning cert files to 10000, always verify mode includes 0400
- Use chmod 0400/0444 for CA bundles consumed by Harbor
- Add a stat-based preflight to install runbooks for TLS material
When it happens
Trigger: harbor.yml sets storage_service.ca_bundle to a file whose stat shows st_uid == 10000 and whose mode lacks 0400 for the owner — e.g. mode 0200, 0000, or 0260 after restrictive chmods.
Common situations: Security hardening scripts that strip read bits; files restored from backups with odd modes; admins chowning to 10000 but not adjusting mode.
Related errors
- Can not get file info
- Error: storage driver %s is not supported, only the followin
- Error: no provider configurations are provided for provider
- Error: storage driver %s is not supported, only the followin
- Error: no provider configurations are provided for provider
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/774e0bad6d06888e.
Report an issue: GitHub.