goharbor/harbor · error · Exception
secret key's length has to be 16 chars, current length: %d
Error message
secret key's length has to be 16 chars, current length: %d
What it means
Thrown by get_secret_key() in make/photon/prepare/utils/cert.py when the persisted secret file (secretkey under the shared secret dir of the data volume, e.g. <data_volume>/secret/secretkey) does not contain exactly 16 characters. Harbor uses this 16-char key as the AES encryption key for credentials (e.g. stored registry/CLAIR secrets), so a wrong length is fatal. The file is normally auto-generated by _get_secret(); a hand-made or corrupted file triggers the check. Note a trailing newline counts as a character (17).
Source
Thrown at make/photon/prepare/utils/cert.py:39
with open(key_file, 'r') as f:
key = f.read()
print("loaded secret from file: %s" % key_file)
mark_file(key_file)
return key
if not os.path.isdir(folder):
os.makedirs(folder)
key = generate_random_string(length)
with open(key_file, 'w') as f:
f.write(key)
print("Generated and saved secret to file: %s" % key_file)
mark_file(key_file)
return key
def get_secret_key(path):
secret_key = _get_secret(path, "secretkey")
if len(secret_key) != 16:
raise Exception("secret key's length has to be 16 chars, current length: %d" % len(secret_key))
return secret_key
def get_alias(path):
alias = _get_secret(path, "defaultalias", length=8)
return alias
@stat_decorator
def create_root_cert(subj, key_path="./k.key", cert_path="./cert.crt"):
rc = subprocess.call(["/usr/bin/openssl", "genrsa", "-traditional", "-out", key_path, "4096"], stdout=DEVNULL, stderr=subprocess.STDOUT)
if rc != 0:
return rc
return subprocess.call(["/usr/bin/openssl", "req", "-new", "-x509", "-key", key_path,\
"-out", cert_path, "-days", "3650", "-subj", subj], stdout=DEVNULL, stderr=subprocess.STDOUT)
def create_ext_file(cn, ext_filename):
with open(ext_filename, 'w') as f:
f.write("subjectAltName = DNS.1:{}".format(cn))View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Write exactly 16 characters with no trailing newline: printf '%s' '0123456789abcdef' > <data_volume>/secret/secretkey
- Or delete the file (rm <data_volume>/secret/secretkey) and re-run prepare so a valid random key is regenerated - only on first-time setups, since existing encrypted data depends on the old key
- For clusters, distribute the identical 16-char key to every node before prepare
- Verify: wc -c <secretkey> must print 16
Example fix
# on the Harbor host (before) $ echo 'mysupersecretkey' > /data/secret/secretkey # 17 chars incl. newline # after $ printf '%s' 'mysupersecretkey1' > /data/secret/secretkey # exactly 16 chars, no newline $ wc -c < /data/secret/secretkey 16
Defensive patterns
Strategy: type-guard
Validate before calling
import os
key_file = os.path.join(data_volume, 'secret', 'secretkey')
if os.path.isfile(key_file):
data = open(key_file).read()
if len(data) != 16:
raise SystemExit('secretkey has length %d, must be 16 - fix or delete the file' % len(data)) Type guard
def has_valid_secret_key(path: str) -> bool:
"""True when the persisted secretkey is exactly 16 chars."""
try:
with open(path) as f:
return len(f.read()) == 16
except OSError:
return False Prevention
- Never create secretkey with echo - printf avoids the trailing newline
- Back up <data_volume>/secret together with the database; the key decrypts stored credentials
- In shared-DB multi-node setups, sync one 16-char key everywhere before first prepare
When it happens
Trigger: An operator manually creates or edits <data_volume>/secret/secretkey with a value whose length != 16 - including echo which appends a newline, a truncated restore, or a multi-line paste. Any subsequent prepare/install run re-reads the file and raises.
Common situations: Following old guides that say to set your own secret key; migrating data volumes where the secret file was recreated; scripts writing keys with printf vs echo differences; multi-node Harbor where each node must share the same 16-char key.
Related errors
- Path exists and the type is regular file
- Please specify hostname
- Can not get file info
- Error: The path for certificate key: %s is invalid
- empty password
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/242b11d378384b8a.
Report an issue: GitHub.