nats-io/nats-server · warning
%v unable to flush session: %v
Error message
%v unable to flush session: %v
What it means
Not an independent throw site: it is the deferred cleanup in policyPCRPasswordSession that augments an existing error when flushing the auth session fails during error unwinding. The message is '%v\nunable to flush session: %v' — the original error plus the flush failure.
Source
Thrown at server/tpm/js_ek_tpm_windows.go:219
// Returns session handle and policy digest.
func policyPCRPasswordSession(rwc io.ReadWriteCloser, pcr int) (sessHandle tpmutil.Handle, policy []byte, retErr error) {
sessHandle, _, err := tpm2.StartAuthSession(
rwc,
tpm2.HandleNull, /*tpmKey*/
tpm2.HandleNull, /*bindKey*/
make([]byte, 16), /*nonceCaller*/
nil, /*secret*/
tpm2.SessionPolicy,
tpm2.AlgNull,
tpm2.AlgSHA256)
if err != nil {
return tpm2.HandleNull, nil, fmt.Errorf("unable to start session: %v", err)
}
defer func() {
if sessHandle != tpm2.HandleNull && err != nil {
if err := tpm2.FlushContext(rwc, sessHandle); err != nil {
retErr = fmt.Errorf("%v\nunable to flush session: %v", retErr, err)
}
}
}()
pcrSelection := tpm2.PCRSelection{
Hash: tpm2.AlgSHA256,
PCRs: []int{pcr},
}
if err := tpm2.PolicyPCR(rwc, sessHandle, nil, pcrSelection); err != nil {
return sessHandle, nil, fmt.Errorf("unable to bind PCRs to auth policy: %v", err)
}
if err := tpm2.PolicyPassword(rwc, sessHandle); err != nil {
return sessHandle, nil, fmt.Errorf("unable to require password for auth policy: %v", err)
}
policy, err = tpm2.PolicyGetDigest(rwc, sessHandle)
if err != nil {
return sessHandle, nil, fmt.Errorf("unable to get policy digest: %v", err)
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Focus on the FIRST line of the error (the original cause); the flush failure is secondary.
- Ensure the rwc connection stays open until policyPCRPasswordSession returns.
- If flush errors recur, check TPM health/reset the device.
Defensive patterns
Strategy: try-catch
Try / catch
_, _, err := policyPCRPasswordSession(rwc, pcr)
if err != nil {
lines := strings.SplitN(err.Error(), "\n", 2)
log.Printf("primary error: %s", lines[0]) // flush failure (if any) is line 2
} Prevention
- Keep the TPM connection open until all deferred cleanups complete.
- Treat the first error line as the root cause when parsing.
- Monitor for repeated flush failures as a sign of TPM hardware issues.
When it happens
Trigger: An earlier step (PolicyPCR, PolicyPassword, PolicyGetDigest) failed AND the deferred tpm2.FlushContext on the still-open sessHandle also failed.
Common situations: TPM became unresponsive mid-operation; connection closed before deferred cleanup ran; rare, secondary failure masking attention from the primary error.
Related errors
- unable to seal data: %v
- unable to write key file: %v
- unable to load data: %v
- unable to get auth session: %v
- unable to unseal data: %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/7aa711d1c97d9d12.
Report an issue: GitHub.