{"record":{"id":"242b11d378384b8a","repo":"goharbor/harbor","slug":"secret-key-s-length-has-to-be-16-chars-current-le","errorCode":null,"errorMessage":"secret key's length has to be 16 chars, current length: %d","messagePattern":"secret key's length has to be 16 chars, current length: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/utils/cert.py","lineNumber":39,"sourceCode":"        with open(key_file, 'r') as f:\n            key = f.read()\n            print(\"loaded secret from file: %s\" % key_file)\n        mark_file(key_file)\n        return key\n    if not os.path.isdir(folder):\n        os.makedirs(folder)\n    key = generate_random_string(length)\n    with open(key_file, 'w') as f:\n        f.write(key)\n        print(\"Generated and saved secret to file: %s\" % key_file)\n    mark_file(key_file)\n    return key\n\n\ndef get_secret_key(path):\n    secret_key = _get_secret(path, \"secretkey\")\n    if len(secret_key) != 16:\n        raise Exception(\"secret key's length has to be 16 chars, current length: %d\" % len(secret_key))\n    return secret_key\n\n\ndef get_alias(path):\n    alias = _get_secret(path, \"defaultalias\", length=8)\n    return alias\n\n@stat_decorator\ndef create_root_cert(subj, key_path=\"./k.key\", cert_path=\"./cert.crt\"):\n   rc = subprocess.call([\"/usr/bin/openssl\", \"genrsa\", \"-traditional\", \"-out\", key_path, \"4096\"], stdout=DEVNULL, stderr=subprocess.STDOUT)\n   if rc != 0:\n        return rc\n   return subprocess.call([\"/usr/bin/openssl\", \"req\", \"-new\", \"-x509\", \"-key\", key_path,\\\n        \"-out\", cert_path, \"-days\", \"3650\", \"-subj\", subj], stdout=DEVNULL, stderr=subprocess.STDOUT)\n\ndef create_ext_file(cn, ext_filename):\n    with open(ext_filename, 'w') as f:\n        f.write(\"subjectAltName = DNS.1:{}\".format(cn))","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/utils/cert.py#L21-L57","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# on the Harbor host (before)\n$ echo 'mysupersecretkey' > /data/secret/secretkey   # 17 chars incl. newline\n\n# after\n$ printf '%s' 'mysupersecretkey1' > /data/secret/secretkey   # exactly 16 chars, no newline\n$ wc -c < /data/secret/secretkey\n16","handlingStrategy":"type-guard","validationCode":"import os\nkey_file = os.path.join(data_volume, 'secret', 'secretkey')\nif os.path.isfile(key_file):\n    data = open(key_file).read()\n    if len(data) != 16:\n        raise SystemExit('secretkey has length %d, must be 16 - fix or delete the file' % len(data))","typeGuard":"def has_valid_secret_key(path: str) -> bool:\n    \"\"\"True when the persisted secretkey is exactly 16 chars.\"\"\"\n    try:\n        with open(path) as f:\n            return len(f.read()) == 16\n    except OSError:\n        return False","tryCatchPattern":null,"preventionTips":["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"],"tags":["harbor","secrets","encryption","installation","file-system"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}