getsops/sops · error
failed to encrypt sops data key to Vault transit backend '%s
Error message
failed to encrypt sops data key to Vault transit backend '%s': %w
What it means
This error wraps any failure returned by the Vault API when SOPS writes the data key to the transit encrypt endpoint (`<enginePath>/encrypt/<keyName>`) during MasterKey.EncryptContext. It means the Vault server itself rejected or could not complete the transit encrypt request (auth, permissions, key existence, connectivity). SOPS wraps the underlying client error so the failing transit path is included.
Source
Thrown at hcvault/keysource.go:240
func (key *MasterKey) Encrypt(dataKey []byte) error {
return key.EncryptContext(context.Background(), dataKey)
}
// EncryptContext takes a SOPS data key, encrypts it with Vault Transit, and stores
// the result in the EncryptedKey field.
func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error {
fullPath := key.encryptPath()
client, err := vaultClient(key.VaultAddress, key.token, key.httpClient)
if err != nil {
log.WithField("Path", fullPath).Info("Encryption failed")
return err
}
secret, err := client.Logical().WriteWithContext(ctx, fullPath, encryptPayload(dataKey))
if err != nil {
log.WithField("Path", fullPath).Info("Encryption failed")
return fmt.Errorf("failed to encrypt sops data key to Vault transit backend '%s': %w", fullPath, err)
}
encryptedKey, err := encryptedKeyFromSecret(secret)
if err != nil {
log.WithField("Path", fullPath).Info("Encryption failed")
return fmt.Errorf("failed to encrypt sops data key to Vault transit backend '%s': %w", fullPath, err)
}
key.EncryptedKey = encryptedKey
log.WithField("Path", fullPath).Info("Encryption successful")
return nil
}
// EncryptIfNeeded encrypts the provided SOPS data key, if it has not been
// encrypted yet.
func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
if key.EncryptedKey == "" {
return key.Encrypt(dataKey)
}View on GitHub (pinned to 13442bb981)
Solutions
- Run `vault status` and `vault token lookup` to confirm the server is reachable and the token is valid.
- Verify the key exists: `vault read <enginePath>/keys/<KeyName>`; create it with `vault write -f <enginePath>/keys/<KeyName>` if missing.
- Check token policy grants `update` on `<enginePath>/encrypt/*` (`vault policy read`).
- Confirm the hc_vault URI path parses to the intended engine path and key name (format https://vault:8200/v1/<engine>/keys/<keyName>).
- Check network/TLS: curl the Vault health endpoint; ensure VAULT_ADDR/VAULT_CACERT are consistent.
- If Vault is sealed, unseal it: `vault operator unseal`.
Example fix
// before: sops config with wrong key name hc_vault: https://vault.example.com/v1/transit/keys/prod-key // after: key name matching what exists in Vault (created via `vault write -f transit/keys/sops`) hc_vault: https://vault.example.com/v1/transit/keys/sops
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: verify reachability and auth before encrypting
func checkVault(addr, token string) error {
cfg := api.DefaultConfig()
cfg.Address = addr
client, err := api.NewClient(cfg)
if err != nil { return err }
if token != "" { client.SetToken(token) }
if _, err := client.Sys().Health(); err != nil { return err }
_, err = client.Auth().Token().LookupSelf()
return err
} Try / catch
if err := key.EncryptContext(ctx, dataKey); err != nil {
var ve *api.ResponseError
if errors.As(err, &ve) {
log.Printf("vault %d on %s: %s", ve.StatusCode, fullPath, ve.Errors)
}
return fmt.Errorf("vault encrypt failed (check token/policy/key existence): %w", err)
} Prevention
- Run `vault token lookup` in CI before sops encrypt/decrypt to catch expired tokens.
- Pin the hc_vault URI (address + engine path + key name) and validate the key exists with `vault read transit/keys/<name>`.
- Grant the token only the transit encrypt/decrypt update capabilities it needs.
- Set VAULT_ADDR/VAULT_CACERT consistently with the URI scheme to avoid TLS mismatches.
- Alert on Vault sealed status so operators unseal before sops jobs run.
When it happens
Trigger: client.Logical().WriteWithContext(ctx, fullPath, encryptPayload(dataKey)) returns a non-nil error in EncryptContext — e.g. HTTP 403 from missing/invalid token, 404 for unknown key name or engine path, 400 invalid request, or network/TLS failure reaching the Vault address.
Common situations: VAULT_TOKEN expired or ~/.vault-token stale; token lacks `update` capability on transit/encrypt/<keyName>; typo'd KeyName or EnginePath in the sops creation rule (hc_vault:// URI); transit engine not mounted at the given path; Vault behind a proxy/DNS that is unreachable; Vault sealed.
Related errors
- failed to decrypt sops data key from Vault transit backend '
- transit backend is empty
- failed to get Azure token credential to encrypt data: %w
- failed to encrypt sops data key with Azure Key Vault key '%s
- failed to create HuaweiCloud KMS client: %w
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/5436ecc166addde0.
Report an issue: GitHub.