{"record":{"id":"b21fa90f856e2645","repo":"getsops/sops","slug":"no-encrypted-data","errorCode":null,"errorMessage":"no encrypted data","messagePattern":"no encrypted data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hcvault/keysource.go","lineNumber":357,"sourceCode":"}\n\n// encryptPayload returns the payload for an encrypt request of the dataKey.\nfunc encryptPayload(dataKey []byte) map[string]interface{} {\n\tencoded := base64.StdEncoding.EncodeToString(dataKey)\n\treturn map[string]interface{}{\n\t\t\"plaintext\": encoded,\n\t}\n}\n\n// encryptedKeyFromSecret attempts to extract the encrypted key from the data\n// of the provided secret.\nfunc encryptedKeyFromSecret(secret *api.Secret) (string, error) {\n\tif secret == nil || secret.Data == nil {\n\t\treturn \"\", fmt.Errorf(\"transit backend is empty\")\n\t}\n\tencrypted, ok := secret.Data[\"ciphertext\"]\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"no encrypted data\")\n\t}\n\tencryptedKey, ok := encrypted.(string)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"encrypted ciphertext cannot be cast to string\")\n\t}\n\treturn encryptedKey, nil\n}\n\n// decryptPayload returns the payload for a decrypt request of the\n// encryptedKey.\nfunc decryptPayload(encryptedKey string) map[string]interface{} {\n\treturn map[string]interface{}{\n\t\t\"ciphertext\": encryptedKey,\n\t}\n}\n\n// dataKeyFromSecret attempts to extract the data key from the data of the\n// provided secret.","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/hcvault/keysource.go#L339-L375","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: encrypting against a KV mount returns data without ciphertext\nkeyservice: hcvault://vault.example.com:8200/secret/data/mykey\n// after: point at the transit engine and key\nkeyservice: hcvault://vault.example.com:8200/transit/keys/mykey","handlingStrategy":"validation","validationCode":"// Call the Vault transit encrypt endpoint directly and assert the field exists\nresp, err := client.Logical().Write(\"transit/encrypt/\"+keyName, map[string]interface{}{\"plaintext\": b64})\nif err != nil { log.Fatal(err) }\nif resp == nil || resp.Data == nil {\n    log.Fatal(\"transit response has no data\")\n}\nif _, ok := resp.Data[\"ciphertext\"]; !ok {\n    log.Fatal(\"transit mount returned no ciphertext field; check mount path is a transit engine\")\n}","typeGuard":"func hasCiphertext(secret *api.Secret) bool {\n    if secret == nil || secret.Data == nil { return false }\n    v, ok := secret.Data[\"ciphertext\"]\n    if !ok { return false }\n    _, isStr := v.(string)\n    return isStr\n}","tryCatchPattern":null,"preventionTips":["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>"],"tags":["vault","transit","kms","go"],"backgroundTag":"vault-transit-ciphertext-missing","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}