{"record":{"id":"62b51a64f8c748f2","repo":"nats-io/nats-server","slug":"unable-to-start-session-v","errorCode":null,"errorMessage":"unable to start session: %v","messagePattern":"unable to start session: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/tpm/js_ek_tpm_windows.go","lineNumber":214,"sourceCode":"func policyPCRPasswordSession(rwc io.ReadWriteCloser, pcr int) (sessHandle tpmutil.Handle, policy []byte, retErr error) {\n\tsessHandle, _, err := tpm2.StartAuthSession(\n\t\trwc,\n\t\ttpm2.HandleNull,  /*tpmKey*/\n\t\ttpm2.HandleNull,  /*bindKey*/\n\t\tmake([]byte, 16), /*nonceCaller*/\n\t\tnil,              /*secret*/\n\t\ttpm2.SessionPolicy,\n\t\ttpm2.AlgNull,\n\t\ttpm2.AlgSHA256)\n\tif err != nil {\n\t\treturn tpm2.HandleNull, nil, fmt.Errorf(\"unable to start session: %v\", err)\n\t}\n\tpcrSelection := tpm2.PCRSelection{\n\t\tHash: tpm2.AlgSHA256,\n\t\tPCRs: []int{pcr},\n\t}\n\tif err := tpm2.PolicyPCR(rwc, sessHandle, nil, pcrSelection); err != nil {\n\t\treturn sessHandle, nil, fmt.Errorf(\"unable to bind PCRs to auth policy: %v\", err)\n\t}\n\treturn sessHandle, policy, nil\n}","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/tpm/js_ek_tpm_windows.go#L196-L232","documentation":"tpm2.StartAuthSession failed when policyPCRPasswordSession tried to open a policy session (SHA-256, unbound, salted-null) with the TPM. No authorization session exists, so neither sealing nor unsealing of the JetStream key can proceed. Common causes: TPM busy/out of session slots, device I/O errors, or unsupported session/algorithm combination.","triggerScenarios":"tpm2.StartAuthSession(...) returns error — TPM session table exhausted, transient failures, or the device handle is invalid/closed.","commonSituations":"Too many concurrent TPM sessions (leaked sessions from prior errors); rwc closed before this call; TPM under heavy load or in a lockout state.","solutions":["Check the wrapped TPM error for TPM_RC_SESSION_HANDLES exhaustion or I/O failure","Close leaked sessions or reset the TPM if session slots are exhausted","Verify the TPM device is accessible and supports policy sessions with SHA-256","Retry the operation after the TPM recovers"],"exampleFix":"// before: session leaks accumulate\nsessCreate, _, err := tpm2.StartAuthSession(...)\n// after: always flush even on later failure (already done here) and cap concurrency\nsem := make(chan struct{}, 1) // serialize TPM session usage\nsem <- struct{}{}\nsessCreate, _, err := tpm2.StartAuthSession(...)","handlingStrategy":"retry","validationCode":"if _, err := rwc.Write(nil); err != nil { // connection sanity probe\n\treturn fmt.Errorf(\"TPM connection dead: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"sessHandle, policy, err := policyPCRPasswordSession(rwc, pcr)\nif err != nil && strings.Contains(err.Error(), \"unable to start session\") {\n\ttime.Sleep(250 * time.Millisecond) // transient TPM busyness\n\tsessHandle, policy, err = policyPCRPasswordSession(rwc, pcr)\n}","preventionTips":["Serialize TPM access to avoid exhausting the session table.","Audit code paths for sessions started without FlushContext.","Open the TPM connection lazily, just before use.","Reboot/reset the TPM if session exhaustion recurs."],"tags":["tpm","windows","auth-session","go"],"backgroundTag":"tpm-session-start-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}