{"record":{"id":"21a0b90571f1ff06","repo":"getsops/sops","slug":"failed-to-open-s-file-w","errorCode":null,"errorMessage":"failed to open %s file: %w","messagePattern":"failed to open (.+?) file: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"age/keysource.go","lineNumber":428,"sourceCode":"// found references, and expects at least one configuration to be present.\nfunc (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {\n\tidentities, unusedLocations, errs := key.loadAgeSSHIdentities()\n\n\tvar readers = make(map[string]identityReader, 0)\n\n\tif ageKey, ok := os.LookupEnv(SopsAgeKeyEnv); ok {\n\t\treaders[SopsAgeKeyEnv] = identityReader{\n\t\t\treader:                   strings.NewReader(ageKey),\n\t\t\tallowMultipleKeysPerLine: true,\n\t\t}\n\t} else {\n\t\tunusedLocations = append(unusedLocations, SopsAgeKeyEnv)\n\t}\n\n\tif ageKeyFile, ok := os.LookupEnv(SopsAgeKeyFileEnv); ok {\n\t\tf, err := os.Open(ageKeyFile)\n\t\tif err != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"failed to open %s file: %w\", SopsAgeKeyFileEnv, err))\n\t\t} else {\n\t\t\tdefer f.Close()\n\t\t\treaders[SopsAgeKeyFileEnv] = identityReader{\n\t\t\t\treader:                   f,\n\t\t\t\tallowMultipleKeysPerLine: false,\n\t\t\t}\n\t\t}\n\t} else {\n\t\tunusedLocations = append(unusedLocations, SopsAgeKeyFileEnv)\n\t}\n\n\tif ageKeyCmd, ok := os.LookupEnv(SopsAgeKeyCmdEnv); ok {\n\t\tout, err := getOutputFromCmd(ageKeyCmd, []string{fmt.Sprintf(\"%s=%s\", SopsAgeRecipientEnv, key.Recipient)})\n\t\tif err != nil {\n\t\t\terrs = append(errs, err)\n\t\t} else {\n\t\t\treaders[SopsAgeKeyCmdEnv] = identityReader{\n\t\t\t\treader:                   bytes.NewReader(out),","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/age/keysource.go#L410-L446","documentation":"SOPS looked for age identities in the file pointed to by the SOPS_AGE_KEY_FILE environment variable and os.Open failed — typically because the path doesn't exist, is a directory, or is unreadable. The error is collected as one of the candidate-location failures during loadIdentities; if no other key source succeeds, decryption fails with this error chained in the aggregate.","triggerScenarios":"SOPS_AGE_KEY_FILE is set, loadIdentities calls os.Open on its value, and the open fails (ENOENT, EACCES, EISDIR).","commonSituations":"Typo in the path or filename; file deleted after provisioning; path valid for the user but sops runs in a container/CI where it was never copied; relative path resolved against a different working directory; pointing at a directory instead of a file.","solutions":["Verify the file exists at the exact path: ls -l \"$SOPS_AGE_KEY_FILE\".","Check permissions: the user running sops must be able to read it (chmod 600, correct owner).","Use an absolute path (e.g. $HOME/.config/sops/age/keys.txt) to avoid working-directory surprises in CI/containers.","Confirm the variable is exported and spelled SOPS_AGE_KEY_FILE in the environment running sops.","As an alternative, place the key at the default location ~/.config/sops/age/keys.txt and unset SOPS_AGE_KEY_FILE."],"exampleFix":"// before\nexport SOPS_AGE_KEY_FILE=\"./keys.txt\"   # not in CI working dir\n// failed to open SOPS_AGE_KEY_FILE file: open ./keys.txt: no such file or directory\n\n// after\nexport SOPS_AGE_KEY_FILE=\"$HOME/.config/sops/age/keys.txt\"\nls -l \"$SOPS_AGE_KEY_FILE\"   # verify readable before running sops","handlingStrategy":"validation","validationCode":"// shell pre-flight\nif [ -n \"$SOPS_AGE_KEY_FILE\" ]; then\n  [ -f \"$SOPS_AGE_KEY_FILE\" ] || { echo \"not a readable file: $SOPS_AGE_KEY_FILE\"; exit 1; }\n  [ -r \"$SOPS_AGE_KEY_FILE\" ] || { echo \"not readable: $SOPS_AGE_KEY_FILE\"; exit 1; }\nfi","typeGuard":null,"tryCatchPattern":"out, err := runSopsDecrypt()\nif err != nil && strings.Contains(err.Error(), \"failed to open \"+\"SOPS_AGE_KEY_FILE\") {\n    return fmt.Errorf(\"check SOPS_AGE_KEY_FILE path/permissions: %w\", err)\n}","preventionTips":["Use absolute paths anchored on $HOME; never relative paths in shared scripts.","Provision the key file (and chmod 600) during machine/CI bootstrap.","Verify with ls -l \"$SOPS_AGE_KEY_FILE\" in setup steps.","Keep the file a regular file; mount secrets as files, not directories.","Export the variable in the same environment that runs sops (CI env mapping, direnv)."],"tags":["age","file-io","env-var","permissions"],"backgroundTag":"file-open-failed","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}