{"record":{"id":"c518013e13e48017","repo":"semaphoreui/semaphore","slug":"encryption-keys-active-s-key-file-w","errorCode":null,"errorMessage":"encryption_keys.active.%s_key_file: %w","messagePattern":"encryption_keys\\.active\\.(.+?)_key_file: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/config.go","lineNumber":1558,"sourceCode":"\tif label != \"\" {\n\t\tmaterial, ok := byLabel[label]\n\t\tif !ok {\n\t\t\treturn \"\", fmt.Errorf(\"encryption_keys.active.%s_key: no key labelled %q\", kind, label)\n\t\t}\n\t\treturn material, nil\n\t}\n\n\tif file != \"\" {\n\t\tif material, ok := byLabel[file]; ok {\n\t\t\treturn material, nil\n\t\t}\n\t\tpath := file\n\t\tif !filepath.IsAbs(path) && enc != nil {\n\t\t\tpath = filepath.Join(enc.KeysFolder, file)\n\t\t}\n\t\tdata, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"encryption_keys.active.%s_key_file: %w\", kind, err)\n\t\t}\n\t\tmaterial := strings.TrimSpace(string(data))\n\t\tif err := addLabeled(file, material); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn material, nil\n\t}\n\n\treturn flat, nil\n}\n\n// loadKeysFolder reads every regular file in folder as one key, labelled by its\n// filename. Dot-prefixed entries (e.g. Kubernetes' \"..data\" / \"..2024_*\") are\n// skipped; symlinks (how K8s mounts secret files) are followed via Stat.\nfunc loadKeysFolder(folder string, addLabeled func(string, string) error) error {\n\tentries, err := os.ReadDir(folder)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encryption_keys.keys_folder %q: %w\", folder, err)","sourceCodeStart":1540,"sourceCodeEnd":1576,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1540-L1576","documentation":"resolveActiveKey wraps the os.ReadFile failure for encryption_keys.active.<kind>_file. Relative paths are resolved against encryption_keys.keys_folder; the wrapped OS error (ENOENT, permissions, directory) is preserved via %w.","triggerScenarios":"active.option_key_file / secret_key_file naming a file that does not exist in keys_folder (or at the absolute path), the folder not being mounted, or permissions blocking the read.","commonSituations":"K8s secret mounted at a different path than configured; file deleted during key rotation before the config was updated; relative filename used but keys_folder not set; symlink targets unreadable.","solutions":["Verify the file exists where it resolves: keys_folder/<file> (or the absolute path given): `ls -l <resolved-path>`","Set encryption_keys.keys_folder correctly so relative filenames resolve","Remount/mount the secret volume containing the key file","Fix permissions so the semaphore process can read the file"],"exampleFix":"# before\nencryption_keys:\n  active:\n    option_key_file: option.key   # file missing\n  keys_folder: /etc/semaphore/keys\n# after  (place option.key into /etc/semaphore/keys)\nencryption_keys:\n  active:\n    option_key_file: option.key\n  keys_folder: /etc/semaphore/keys   # must contain option.key","handlingStrategy":"validation","validationCode":"path := cfg.Encryption.Active.OptionKeyFile\nif !filepath.IsAbs(path) && cfg.Encryption.KeysFolder != \"\" {\n    path = filepath.Join(cfg.Encryption.KeysFolder, path)\n}\nif _, err := os.Stat(path); err != nil {\n    return fmt.Errorf(\"active.option_key_file resolves to missing file %s\", path)\n}","typeGuard":"func keyFileReadable(cfg *util.EncryptionKeysConfig, file string) bool {\n    if file == \"\" { return false }\n    p := file\n    if !filepath.IsAbs(p) && cfg != nil { p = filepath.Join(cfg.KeysFolder, p) }\n    _, err := os.Stat(p)\n    return err == nil\n}","tryCatchPattern":"material, err := resolveActiveKey(enc, flat, byLabel, addLabeled, ptr, \"option\")\nif err != nil {\n    return nil, fmt.Errorf(\"active key file problem: %w\", err)\n}","preventionTips":["Always set keys_folder when using relative active key filenames","Verify resolved paths (folder + filename) exist inside the container before deploy","Check mounts after secret rotation — files can disappear if the volume changes","Use absolute paths when the folder layout is fixed"],"tags":["config","encryption","file","filesystem","semaphore"],"backgroundTag":"file-read-failed","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"}