{"record":{"id":"29dc0eb882d38827","repo":"semaphoreui/semaphore","slug":"access-key-encryption-has-invalid-decoded-length","errorCode":null,"errorMessage":"access_key_encryption has invalid decoded length %d bytes; AES requires 16, 24, or 32 bytes (use `openssl rand -base64 32` to generate a valid key)","messagePattern":"access_key_encryption has invalid decoded length (.+?) bytes; AES requires 16, 24, or 32 bytes \\(use `openssl rand -base64 32` to generate a valid key\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"util/config.go","lineNumber":1742,"sourceCode":"\n\treturn &enc, nil\n}\n\nfunc validateAccessKeyEncryption(key string) error {\n\tif key == \"\" {\n\t\treturn nil\n\t}\n\n\tencryption, err := base64.StdEncoding.DecodeString(key)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"access_key_encryption must be a valid base64 string: %w\", err)\n\t}\n\n\tswitch len(encryption) {\n\tcase 16, 24, 32:\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\n\t\t\t\"access_key_encryption has invalid decoded length %d bytes; AES requires 16, 24, or 32 bytes (use `openssl rand -base64 32` to generate a valid key)\",\n\t\t\tlen(encryption),\n\t\t)\n\t}\n}\n\nfunc validateConfig() {\n\terr := validate(Config)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tif err := validateAccessKeyEncryption(Config.AccessKeyEncryption); err != nil {\n\t\tpanic(err)\n\t}\n\tif err := validateAccessKeyEncryption(Config.OptionEncryption); err != nil {\n\t\tpanic(err)\n\t}","sourceCodeStart":1724,"sourceCodeEnd":1760,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1724-L1760","documentation":"The access_key_encryption value decoded from base64 successfully, but its byte length is not 16, 24, or 32 — the only key sizes AES accepts (AES-128/192/256). The error reports the actual decoded length and suggests generating a key with `openssl rand -base64 32`. It fails startup via panic in validateConfig.","triggerScenarios":"validateAccessKeyEncryption() decodes a non-empty access_key_encryption/option_encryption value and the switch on len(encryption) hits the default case (decoded length not in {16,24,32}).","commonSituations":"User generated `openssl rand -base64 16` thinking 16 chars, but truncating a 32-byte base64 string yields e.g. 20 decoded bytes; base64 of a short password (e.g. 8-10 bytes); re-encoding an already-base64 string (double encoding changes length); hand-typed key of arbitrary length.","solutions":["Generate a fresh valid key with `openssl rand -base64 32` and replace the configured value.","Pad/truncate key material to exactly 16, 24, or 32 decoded bytes — verify with `base64 -d <value> | wc -c`.","Do not double-encode: if the value already looks base64, decode it, check its length, and use the correct single encoding.","If old data was encrypted with a 16/24/32-byte key, recover that exact key; you cannot change lengths without re-encrypting existing access keys."],"exampleFix":"// before: 20-byte decoded key\nexport SEMAPHORE_ACCESS_KEY_ENCRYPTION=$(openssl rand -base64 15)  # decodes to 15 bytes\n// after\nexport SEMAPHORE_ACCESS_KEY_ENCRYPTION=$(openssl rand -base64 32)  # decodes to 32 bytes","handlingStrategy":"validation","validationCode":"raw, err := base64.StdEncoding.DecodeString(value)\nif err != nil {\n    log.Fatal(\"not base64\")\n}\nswitch len(raw) {\ncase 16, 24, 32:\n    // ok\ndefault:\n    log.Fatalf(\"decoded %d bytes; need 16/24/32\", len(raw))\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"invalid AES key length: %v\", r)\n    }\n}()","preventionTips":["Use `openssl rand -base64 32` verbatim — never truncate its output.","Remember `openssl rand -base64 N` decodes to ~N bytes; N must be 16, 24, or 32.","Never double-encode; if a value already looks like base64, decode and inspect before reuse."],"tags":["config","aes","base64","key-length","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}