nats-io/nats-server · error

unable to regenerate SRK from the TPM: %v

Error message

unable to regenerate SRK from the TPM: %v

What it means

Wraps the error returned by regenerateSRK() while rebuilding the Storage Root Key handle inside LoadJetStreamEncryptionKeyFromTPM. It fires when the TPM rejects the SRK regeneration, typically because the supplied SRK password is wrong or the TPM is in a bad/unavailable state, aborting retrieval of the JetStream encryption key.

Source

Thrown at server/tpm/js_ek_tpm_windows.go:258

// LoadJetStreamEncryptionKeyFromTPM loads the JetStream encryption key from the TPM.
// If the keyfile does not exist, a key will be created and sealed. Public and private blobs
// used to decrypt the key in future sessions will be saved to disk in the file provided.
// The key will be unsealed and returned only with the correct password and PCR value.
func LoadJetStreamEncryptionKeyFromTPM(srkPassword, jsKeyFile, jsKeyPassword string, pcr int) (string, error) {
	rwc, err := tpm2.OpenTPM()
	if err != nil {
		return "", fmt.Errorf("could not open the TPM: %v", err)
	}
	defer rwc.Close()

	// Load the key from the TPM
	srkHandle, err := regenerateSRK(rwc, srkPassword)
	defer func() {
		tpm2.FlushContext(rwc, srkHandle)
	}()
	if err != nil {
		return "", fmt.Errorf("unable to regenerate SRK from the TPM: %v", err)
	}
	// Read the keys from the key file. If the filed doesn't exist it means we need to create
	// a new js encrytpion key.
	publicBlob, privateBlob, err := readTPMKeysFromFile(jsKeyFile)
	if err != nil {
		if os.IsNotExist(err) {
			jsek, err := createAndSealJsEncryptionKey(rwc, srkHandle, srkPassword, jsKeyFile, jsKeyPassword, pcr)
			if err != nil {
				return "", fmt.Errorf("unable to generate new key from the TPM: %v", err)
			}
			// we've created and sealed the JS Encryption key, now we just return it.
			return jsek, nil
		}
		return "", fmt.Errorf("unable to load key from TPM: %v", err)
	}

	// Unseal the JetStream encryption key using the TPM.
	jsek, err := unsealJsEncrpytionKey(rwc, pcr, srkHandle, srkPassword, jsKeyPassword, publicBlob, privateBlob)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Verify the srkPassword passed to LoadJetStreamEncryptionKeyFromTPM matches the one used when the SRK was originally created
  2. Check TPM availability and health (tpm2.OpenTPM already succeeded, so confirm the device is responsive)
  3. If the SRK cannot be recovered, re-provision the TPM and recreate the sealed JetStream key
  4. Retry after confirming no other process holds exclusive access to the TPM
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at server/tpm/js_ek_tpm_windows.go:258 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/70e673375250f8e8. Report an issue: GitHub.