getsops/sops · error
no encrypted data
Error message
no encrypted data
What it means
This error comes from encryptedKeyFromSecret in the HashiCorp Vault transit keysource helper. It means Vault returned a valid secret whose Data map exists, but the map contains no "ciphertext" key. The library throws it because without a ciphertext entry it cannot wrap the data-encryption key during EncryptContext.
Source
Thrown at hcvault/keysource.go:357
}
// encryptPayload returns the payload for an encrypt request of the dataKey.
func encryptPayload(dataKey []byte) map[string]interface{} {
encoded := base64.StdEncoding.EncodeToString(dataKey)
return map[string]interface{}{
"plaintext": encoded,
}
}
// encryptedKeyFromSecret attempts to extract the encrypted key from the data
// of the provided secret.
func encryptedKeyFromSecret(secret *api.Secret) (string, error) {
if secret == nil || secret.Data == nil {
return "", fmt.Errorf("transit backend is empty")
}
encrypted, ok := secret.Data["ciphertext"]
if !ok {
return "", fmt.Errorf("no encrypted data")
}
encryptedKey, ok := encrypted.(string)
if !ok {
return "", fmt.Errorf("encrypted ciphertext cannot be cast to string")
}
return encryptedKey, nil
}
// decryptPayload returns the payload for a decrypt request of the
// encryptedKey.
func decryptPayload(encryptedKey string) map[string]interface{} {
return map[string]interface{}{
"ciphertext": encryptedKey,
}
}
// dataKeyFromSecret attempts to extract the data key from the data of the
// provided secret.View on GitHub (pinned to 13442bb981)
Solutions
- Verify the transit mount path and key name in the SOPS Vault config point to a real transit engine (e.g. /transit/encrypt/<key>).
- Test the same encrypt call with `vault write transit/encrypt/<key> plaintext=$(base64 <<< test)` and inspect that the response JSON has data.ciphertext.
- Check Vault ACL policies (vault policy read) to ensure the token has update capability on the transit encrypt path and responses are not filtered.
- Confirm the Vault server/CLI versions are compatible with the transit API response format used by the api.Secret client.
Example fix
// before: encrypting against a KV mount returns data without ciphertext keyservice: hcvault://vault.example.com:8200/secret/data/mykey // after: point at the transit engine and key keyservice: hcvault://vault.example.com:8200/transit/keys/mykey
Defensive patterns
Strategy: validation
Validate before calling
// Call the Vault transit encrypt endpoint directly and assert the field exists
resp, err := client.Logical().Write("transit/encrypt/"+keyName, map[string]interface{}{"plaintext": b64})
if err != nil { log.Fatal(err) }
if resp == nil || resp.Data == nil {
log.Fatal("transit response has no data")
}
if _, ok := resp.Data["ciphertext"]; !ok {
log.Fatal("transit mount returned no ciphertext field; check mount path is a transit engine")
} Type guard
func hasCiphertext(secret *api.Secret) bool {
if secret == nil || secret.Data == nil { return false }
v, ok := secret.Data["ciphertext"]
if !ok { return false }
_, isStr := v.(string)
return isStr
} Prevention
- Point keyservice URIs at a transit engine mount, never a KV mount
- Validate mount type with `vault secrets list -detailed` before configuring
- Run a manual vault write to the encrypt path as a smoke test
- Keep Vault ACLs minimal but allow update on transit/encrypt/<key>
When it happens
Trigger: Calling EncryptContext (or TestMasterKey_Decrypt) when the Vault transit endpoint returns 200 but the response Data lacks "ciphertext" — e.g. writing to a wrong endpoint path, hitting a non-transit mount, or a Vault version/policy that strips the field.
Common situations: Misconfigured VAULT_TRANSIT_MOUNT or key name pointing at a non-transit secret engine; Vault ACL policies that filter response fields; custom Vault proxy rewriting responses; switching from Vault KV to transit without updating the mount path.
Related errors
- no decrypted data
- encrypted ciphertext cannot be cast to string
- decrypted plaintext data cannot be cast to string
- failed to encrypt sops data key to Vault transit backend '%s
- failed to decrypt sops data key from Vault transit backend '
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/b21fa90f856e2645.
Report an issue: GitHub.