-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Every operation that touches secret files calls the sops binary. If it is not on your PATH or configured with a valid explicit path, SOPS-backed commands fail before decrypting or mutating files.
Fix: Install SOPS and verify it works:
sops --versionIf SOPS is installed to a non-standard location, point Keyseal to it in keyseal.yaml:
sops:
binary: /usr/local/bin/sopsThen rerun keyseal doctor.
Doctor warns when sops.age_binary cannot be found or cannot run --version.
This does not fail doctor because SOPS may still be able to encrypt and decrypt depending on your backend. For the default age-based .sops.yaml, install age or point Keyseal at the right binary:
sops:
age_binary: /usr/local/bin/ageThen rerun:
keyseal doctorkeyseal verify treats this warning as a failure by design. Fix or explicitly accept the local setup before using verify as a release gate.
Every command except init looks for keyseal.yaml in the current working directory. You are either in the wrong directory or the file does not exist.
Fix:
# confirm you are in the right directory
ls keyseal.yaml
# if it does not exist, initialize
keyseal initThe Git-aware commands (status, diff, history, commit, rollback, plus commit-enabled add, edit, and updatekeys) require that your current working directory is inside an existing Git repository.
Fix:
git rev-parse --show-toplevelIf that fails, change into the correct repository or initialize one yourself with git init. Keyseal does not create the Git repository for you.
Keyseal shells out to the git binary for status, diff, history, commit, rollback, and updatekeys --commit behavior.
Fix:
git --versionIf Git is installed in a non-standard location, ensure it is available on PATH before you run Keyseal.
After keyseal init, the generated .sops.yaml contains:
age: age1REPLACE_ME,age1RECOVERY_REPLACE_MESOPS will not encrypt with these values. Doctor will flag them as failures.
Fix: Replace with real age public keys:
# if you need to generate a key pair
age-keygen -o ~/.config/sops/age/keys.txt
# note the public key from the output, then edit .sops.yamlSOPS cannot find a creation rule in .sops.yaml that matches the target file path.
Common cause: The path_regex in your creation rule does not match the path you are trying to encrypt. The regex is matched against the final destination path, or the --filename-override value passed by keyseal add.
Example: if your target is production/platform/app.enc.yaml but your rule is:
path_regex: production/platform/.*\.enc\.yaml$and you have repository.root: ., the path passed to SOPS is relative to where you ran keyseal add. Verify the regex with:
# test the regex against your path
echo "production/platform/app.enc.yaml" | grep -E "production/platform/.*\.enc\.yaml$"Doctor will report:
[fail] production/platform/app.enc.yaml: is non-empty plaintext at an encrypted path
This means the file at that path contains non-empty content but has no SOPS metadata. Keyseal treats that as a plaintext-at-encrypted-path failure even if the content is malformed, because non-empty plaintext secret content must not be ignored.
How this happens: The file was written manually or copied from an example without going through keyseal add or sops encrypt.
Fix:
# remove the plaintext file
rm production/platform/app.enc.yaml
# recreate it properly
keyseal add production/platform/app
# then edit to set real values
keyseal edit production/platform/appDo not commit a plaintext .enc.yaml file to the repository.
Doctor will report a warning and skip decrypt validation for an empty or whitespace-only .enc.yaml file.
This is meant for uninitialized placeholder files that exist in the tree but have not been populated yet.
keyseal render and keyseal exec will skip these files when other requested secrets are usable. If every requested secret is an empty placeholder, the command fails with a clear error instead of silently producing empty output.
keyseal edit <logical-name> can bootstrap the empty file with an encrypted starter document and then open it in SOPS.
Error: mode 0644 is not owner-only; use --force to override
The file mode you specified (or the default in keyseal.yaml) would give read access to group or world users.
Fix: Use 0600 (the default):
keyseal render production/platform/app --out /run/secrets/app.env --mode 0600Or if you genuinely need a less restrictive mode for your deployment:
keyseal render production/platform/app --out ./app.env --mode 0644 --forceKeyseal validates the decrypted secret document after every decrypt. Common causes:
- A key in
valuesdoes not matchvalidation.key_pattern(default requires uppercase + digits + underscores only). This is usually a key with a lowercase letter or a hyphen. - The
valuesmap is empty andvalidation.require_valuesistrue. - The document has
version: 0or is missingversion.
Fix: Run keyseal edit <logical-name> to fix the document, or adjust validation.key_pattern in keyseal.yaml if lowercase keys are intentional.
Error: unknown template "my-template"
Only four templates exist: laravel, stripe, mail, mysql-app. Template names are case-sensitive.
Fix: Check the available templates in Templates or omit --template to use the default single-key starter.
The target .enc.yaml file already exists and you did not pass --force.
Fix:
# overwrite the existing file
keyseal add production/platform/app --force
# or just edit the existing file
keyseal edit production/platform/appkeyseal commit returns this when no Keyseal-managed files currently differ from Git history.
The same message can appear on edit --commit, rollback --commit, or updatekeys --commit when the command completed but did not leave any change to stage.
Fix: Check the filtered status view first:
keyseal statusIf the file is unchanged, there is nothing for Keyseal to commit.
keyseal rollback refuses to overwrite a secret file that already has staged or unstaged local changes.
Fix: Either commit or discard the local change first, then retry the rollback.
To inspect the target rollback safely:
keyseal rollback production/platform/app --to <commit> --dry-run--dry-run is preview-only and does not require the target file to be clean.
Doctor exits 1 when any check has status fail. The failure is printed to stdout, not stderr. If you are running in a context that suppresses stdout, redirect it:
keyseal doctor 2>&1
# or use JSON to separate structured output
keyseal doctor --jsonError: invalid logical name "production/platform/app.enc.yaml": name must not end with .yaml
Common logical name mistakes:
| Bad input | Problem |
|---|---|
production/platform/app.enc.yaml |
Do not include the file extension |
/production/platform/app |
Logical names must be relative |
production/../platform/app |
No path traversal |
production//platform/app |
No empty segments |
If you build without make build (e.g. go build ./cmd/keyseal), the ldflags that inject version metadata are not set. The binary will report keyseal dev.
Fix: Always use make build or make dist for any build you care about the version string of.
Each release archive contains the binary, README.md, and LICENSE in a top-level directory named after the archive. Extract with:
tar xzf keyseal_v1.0.0_linux_amd64.tar.gz
# produces: keyseal_v1.0.0_linux_amd64/keysealVerify the checksum before using the binary:
sha256sum -c keyseal_v1.0.0_checksums.txt --ignore-missingYour age private key is not at the location SOPS expects, or the file was encrypted with a different key.
Keyseal resolves the age key path in this order:
-
SOPS_AGE_KEY_FILEfrom the environment -
sops.age_key_filefromkeyseal.yaml - SOPS default lookup
Check:
# check the env var
echo $SOPS_AGE_KEY_FILE
# inspect the configured fallback path
grep -A2 '^sops:' keyseal.yaml
# try decrypting directly with sops to isolate the issue
sops --decrypt production/platform/app.enc.yamlDoctor will report the SOPS error output (up to 3 lines) when decryption fails.
Getting Started
Reference
Operations
Development