{"record":{"id":"61f27559e4ed8207","repo":"argoproj/argo-workflows","slug":"failed-to-parse-kms-encryption-context-w","errorCode":null,"errorMessage":"failed to parse KMS encryption context: %w","messagePattern":"failed to parse KMS encryption context: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/s3/s3.go","lineNumber":921,"sourceCode":"\treturn err\n}\n\n// buildServerSideEnc creates the minio encryption options when putting encrypted items in a bucket\nfunc (e *EncryptOpts) buildServerSideEnc(bucket, key string) (encrypt.ServerSide, error) {\n\tif e == nil || !e.Enabled {\n\t\treturn nil, nil\n\t}\n\n\tif e.ServerSideCustomerKey != \"\" {\n\t\tencryption := encrypt.DefaultPBKDF([]byte(e.ServerSideCustomerKey), []byte(bucket+key))\n\n\t\treturn encryption, nil\n\t}\n\n\tif e.KmsKeyID != \"\" {\n\t\tencryptionCtx, err := parseKMSEncCntx(e.KmsEncryptionContext)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse KMS encryption context: %w\", err)\n\t\t}\n\n\t\tif encryptionCtx == nil {\n\t\t\t// To overcome a limitation in Minio which checks interface{} == nil.\n\t\t\tkms, kmsErr := encrypt.NewSSEKMS(e.KmsKeyID, nil)\n\t\t\tif kmsErr != nil {\n\t\t\t\treturn nil, kmsErr\n\t\t\t}\n\n\t\t\treturn kms, nil\n\t\t}\n\n\t\tkms, err := encrypt.NewSSEKMS(e.KmsKeyID, encryptionCtx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn kms, nil","sourceCodeStart":903,"sourceCodeEnd":939,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/s3/s3.go#L903-L939","documentation":"When building SSE-KMS encryption, the kmsEncryptionContext string is parsed as JSON; a parse failure is wrapped with this message and fails client construction. The encryption context must be a valid JSON object (it is later base64-encoded for Minio).","triggerScenarios":"Artifact S3 encryptionOptions specify kmsEncryptionContext that is not valid JSON (e.g. raw 'foo=bar', trailing comma, single quotes), and KmsKeyID is set so parseKMSEncCntx runs.","commonSituations":"YAML string values with quotes stripped by templating; users writing k=v style context instead of JSON; Helm values interpolation mangling braces.","solutions":["Set kmsEncryptionContext to a valid JSON object string, e.g. '{\"key\":\"value\"}'","Quote the value carefully in YAML/Helm so braces and quotes survive templating","Validate with jq: echo '<context>' | jq . must succeed","If no context is needed, omit kmsEncryptionContext entirely (nil context is allowed)"],"exampleFix":"// before\nkmsEncryptionContext: department=finance\n// after\nkmsEncryptionContext: '{\"department\":\"finance\"}'","handlingStrategy":"validation","validationCode":"func validKMSContext(s string) bool {\n  if s == \"\" { return true }\n  var m map[string]interface{}\n  return json.Unmarshal([]byte(s), &m) == nil\n}\n// use: if !validKMSContext(cfg.EncryptionOptions.KmsEncryptionContext) { reject }","typeGuard":"func isJSONObject(s string) bool {\n  var v map[string]any\n  return json.Unmarshal([]byte(s), &v) == nil\n}","tryCatchPattern":"if _, err := buildEncryptOpt(e); err != nil && strings.Contains(err.Error(), \"parse KMS encryption context\") {\n  return fmt.Errorf(\"fix kmsEncryptionContext JSON: %w\", err)\n}","preventionTips":["Always write kmsEncryptionContext as a quoted JSON object string","Run echo '$CONTEXT' | jq . as a pre-commit config check","Beware Helm/YAML stripping quotes around braces — wrap in single quotes"],"tags":["s3","encryption","kms","json","configuration"],"backgroundTag":"invalid-kms-encryption-context","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}