nats-io/nats-server · error
unable to marshal keys to JSON: %v
Error message
unable to marshal keys to JSON: %v
What it means
writeTPMKeysToFile failed to serialize the natsTPMPersistedKeys struct (version plus base64-encoded private/public TPM blobs) to JSON before persisting the JetStream key file. In practice json.Marshal on this plain struct of strings/byte slices essentially never fails; if it does, it signals a programming error such as an unsupported field type, not a runtime or I/O problem.
Source
Thrown at server/tpm/js_ek_tpm_windows.go:104
tpmKeys := natsTPMPersistedKeys{
Version: JsKeyTPMVersion,
PrivateKey: make([]byte, base64.StdEncoding.EncodedLen(len(privateBlob))),
PublicKey: make([]byte, base64.StdEncoding.EncodedLen(len(publicBlob))),
}
base64.StdEncoding.Encode(tpmKeys.PrivateKey, privateBlob)
base64.StdEncoding.Encode(tpmKeys.PublicKey, publicBlob)
// Convert to JSON
keysJSON, err := json.Marshal(tpmKeys)
if err != nil {
return fmt.Errorf("unable to marshal keys to JSON: %v", err)
}
// Write the JSON to a file
if err := os.WriteFile(filename, keysJSON, 0640); err != nil {
return fmt.Errorf("unable to write keys file to %q: %v", filename, err)
}
return nilView on GitHub (pinned to 3a66a489d2)
Solutions
- Verify the natsTPMPersistedKeys struct only contains JSON-serializable types (version int, base64 byte slices)
- Retry the key creation; a transient marshal failure of a plain struct is practically impossible
- Inspect the wrapped error to confirm no embedded unsupported values (e.g. channels, funcs) were added to the struct
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at server/tpm/js_ek_tpm_windows.go:104 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/f6087740b147f1a9.
Report an issue: GitHub.