{"record":{"id":"7e1d3281076de129","repo":"getsops/sops","slug":"error-marshaling-to-json-s","errorCode":null,"errorMessage":"Error marshaling to json: %s","messagePattern":"Error marshaling to json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"stores/json/store.go","lineNumber":362,"sourceCode":"\n// EmitEncryptedFile returns the encrypted bytes of the json file corresponding to a\n// sops.Tree runtime object\nfunc (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {\n\tbranches, err := stores.SerializeMetadata(in, stores.MetadataOpts{\n\t\tFlatten: stores.MetadataFlattenNone,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Error marshaling metadata: %s\", err)\n\t}\n\treturn store.EmitPlainFile(branches)\n}\n\n// EmitPlainFile returns the plaintext bytes of the json file corresponding to a\n// sops.TreeBranches runtime object\nfunc (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {\n\tout, err := store.jsonFromTreeBranch(in[0])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Error marshaling to json: %s\", err)\n\t}\n\tout = append(out, '\\n')\n\treturn out, nil\n}\n\n// EmitValue returns bytes corresponding to a single encoded value\n// in a generic interface{} object\nfunc (store *Store) EmitValue(v interface{}) ([]byte, error) {\n\ts, err := store.encodeValue(v)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn store.reindentJSON(s)\n}\n\n// EmitExample returns the bytes corresponding to an example complex tree\nfunc (store *Store) EmitExample() []byte {\n\tbytes, err := store.EmitPlainFile(stores.ExampleComplexTree.Branches)","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/stores/json/store.go#L344-L380","documentation":"Emitted by the JSON Store's EmitPlainFile when jsonFromTreeBranch fails to marshal the first tree branch to JSON. Since the underlying values come from a decoded tree, this usually means a value in the tree is not representable as a JSON value (e.g. a non-string/non-JSON scalar type set programmatically).","triggerScenarios":"Calling EmitPlainFile with a TreeBranches whose first branch contains items with keys that are not strings or values that the store's value-conversion cannot handle (e.g. a TreeItem value of an unexpected Go type inserted programmatically). TestEmitBinaryFileWrongBranches/TestEmitBinaryFileWrongDataType exercise exactly this: wrong branch count or wrong data type in the tree.","commonSituations":"Custom code building a sops.TreeBranch with non-JSON values (nil branch, wrong types), calling EmitPlainFile on an empty TreeBranches slice (index [0] would panic before this, but wrong types hit this error), or post-decryption mutations of tree values.","solutions":["Ensure the tree contains at least one branch whose items all have string keys and JSON-representable values (string, number, bool, nil, nested TreeBranch/slices)","Inspect the wrapped error to find the offending key/type","Normalize unusual value types to strings before emitting","Use the store matching your data type (binary store for opaque data, yaml store for YAML output)"],"exampleFix":"// before\nbranch := sops.TreeBranch{{Key: 123, Value: \"x\"}} // non-string key\nout, err := store.EmitPlainFile(sops.TreeBranches{branch}) // \"Error marshaling to json\"\n// after\nbranch := sops.TreeBranch{{Key: \"123\", Value: \"x\"}}\nout, err := store.EmitPlainFile(sops.TreeBranches{branch})","handlingStrategy":"type-guard","validationCode":"func jsonSafe(branch sops.TreeBranch) error {\n\tfor _, item := range branch {\n\t\tif _, ok := item.Key.(string); !ok {\n\t\t\treturn fmt.Errorf(\"non-string key %T\", item.Key)\n\t\t}\n\t}\n\treturn nil\n}\nif len(branches) == 0 {\n\treturn errors.New(\"need at least one branch\")\n}\nif err := jsonSafe(branches[0]); err != nil { return err }","typeGuard":"func isStringKey(item sops.TreeItem) bool {\n\t_, ok := item.Key.(string)\n\treturn ok\n}","tryCatchPattern":"out, err := store.EmitPlainFile(branches)\nif err != nil {\n\tif strings.HasPrefix(err.Error(), \"Error marshaling to json\") {\n\t\treturn fmt.Errorf(\"tree contains non-JSON-encodable values: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Only put string keys and JSON-representable values in tree branches","Check that TreeBranches is non-empty before calling EmitPlainFile","Use the binary store for opaque data and the yaml store for YAML output"],"tags":["json","marshal","tree","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}