{"record":{"id":"ce269a3da3b11326","repo":"nats-io/nats-server","slug":"unable-to-load-data-v","errorCode":null,"errorMessage":"unable to load data: %v","messagePattern":"unable to load data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/tpm/js_ek_tpm_windows.go","lineNumber":182,"sourceCode":"\t}\n\tprivateArea, publicArea, err := tpm2.Seal(rwc, srkHandle, srkPassword, jsKeyPassword, policy, jsStoreKey)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to seal data: %v\", err)\n\t}\n\terr = writeTPMKeysToFile(jsKeyFile, privateArea, publicArea)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to write key file: %v\", err)\n\t}\n\treturn string(jsStoreKey), nil\n}\n\n// Unseals the JetStream encryption key from the TPM with the provided keys.\n// The key is returned as a string.\nfunc unsealJsEncrpytionKey(rwc io.ReadWriteCloser, pcr int, srkHandle tpmutil.Handle, srkPassword, objectPassword string, publicBlob, privateBlob []byte) (string, error) {\n\t// Load the public/private blobs into the TPM for decryption.\n\tobjectHandle, _, err := tpm2.Load(rwc, srkHandle, srkPassword, publicBlob, privateBlob)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to load data: %v\", err)\n\t}\n\tdefer tpm2.FlushContext(rwc, objectHandle)\n\n\t// Create the authorization session with TPM.\n\tsessHandle, _, err := policyPCRPasswordSession(rwc, pcr)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to get auth session: %v\", err)\n\t}\n\tdefer func() {\n\t\ttpm2.FlushContext(rwc, sessHandle)\n\t}()\n\t// Unseal the data we've loaded into the TPM with the object (js key) password.\n\tunsealedData, err := tpm2.UnsealWithSession(rwc, sessHandle, objectHandle, objectPassword)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to unseal data: %v\", err)\n\t}\n\treturn string(unsealedData), nil\n}","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/tpm/js_ek_tpm_windows.go#L164-L200","documentation":"unsealJsEncrpytionKey could not load the previously sealed key's public/private blobs back into the TPM. tpm2.Load re-imports the object under the SRK; failure typically means the blobs don't match the current SRK or are corrupted.","triggerScenarios":"tpm2.Load(rwc, srkHandle, srkPassword, publicBlob, privateBlob) errors — blobs corrupted/truncated, key file from a different machine/TPM, wrong srkHandle, or wrong srkPassword.","commonSituations":"Copying the key file between machines (TPM-sealed data is TPM-specific); key file truncated by a bad write; TPM was re-provisioned so the SRK changed; swapping private and public blobs.","solutions":["Delete the stale key file and let LoadJetStreamEncryptionKeyFromTPM recreate the key.","Verify the key file was created on the SAME TPM (sealed blobs are not portable).","Confirm srkHandle/srkPassword match those used at seal time.","Check the blobs were not swapped or truncated when written/read."],"exampleFix":"// before: blindly loading stale blobs\nobjectHandle, _, err := tpm2.Load(rwc, srkHandle, srkPassword, publicBlob, privateBlob)\nif err != nil {\n\treturn \"\", fmt.Errorf(\"unable to load data: %v\", err)\n}\n// after: caller fallback — remove key file and re-create on mismatch\nif _, err := tpm2.Load(rwc, srkHandle, srkPassword, publicBlob, privateBlob); err != nil {\n\tos.Remove(jsKeyFile) // force re-seal path\n\treturn LoadJetStreamEncryptionKeyFromTPM(...)\n}","handlingStrategy":"fallback","validationCode":"info, err := os.Stat(jsKeyFile)\nif err != nil || info.Size() == 0 {\n\t// force re-seal path\n\tos.Remove(jsKeyFile)\n}","typeGuard":"func isTPMLoadError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"unable to load data\")\n}","tryCatchPattern":"key, err := LoadJetStreamEncryptionKeyFromTPM(rwc)\nif err != nil && isTPMLoadError(err) {\n\tos.Remove(jsKeyFile) // blobs unusable on this TPM; regenerate\n\tkey, err = LoadJetStreamEncryptionKeyFromTPM(rwc)\n}","preventionTips":["Never copy TPM key files between machines — blobs are TPM-bound.","Detect corrupt/oversized/zero-length key files at startup.","Record which TPM/host created the key file.","Note that deleting the key file invalidates previously encrypted data."],"tags":["tpm","windows","key-loading","blob","go"],"backgroundTag":"tpm-load-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}