nats-io/nats-server · error
unable to create/access directory %q: %v
Error message
unable to create/access directory %q: %v
What it means
Emitted on Windows during JetStream TPM key setup: the directory that should hold the persisted TPM-sealed key blobs could not be created or accessed (os.MkdirAll/open failure). Typical causes are insufficient NTFS permissions for the service account, an invalid path, or the directory being locked by another process; without it the sealed key material cannot be written.
Source
Thrown at server/tpm/js_ek_tpm_windows.go:88
},
}
// Create the parent key against which to seal the data
srkHandle, _, err := tpm2.CreatePrimary(rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", srkPassword, srkTemplate)
return srkHandle, err
}
type natsTPMPersistedKeys struct {
Version int `json:"version"`
PrivateKey []byte `json:"private_key"`
PublicKey []byte `json:"public_key"`
}
// Writes the private and public blobs to disk in a single file. If the directory does
// not exist, it will be created. If the file already exists it will be overwritten.
func writeTPMKeysToFile(filename string, privateBlob []byte, publicBlob []byte) error {
keyDir := filepath.Dir(filename)
if err := os.MkdirAll(keyDir, 0750); err != nil {
return fmt.Errorf("unable to create/access directory %q: %v", keyDir, err)
}
// Create a new set of persisted keys. Note that the private key doesn't necessarily
// need to be protected as the TPM password is required to use unseal, although it's
// a good idea to put this in a secure location accessible to the server.
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 fileView on GitHub (pinned to 3a66a489d2)
Solutions
- Check that the NATS service account has create/write permission on the parent directory (commonly under ProgramData)
- Remove stale lock files or permissions overrides on the target directory
- Manually create the directory with correct ACLs, then restart the server so key sealing can proceed
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at server/tpm/js_ek_tpm_windows.go:88 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/8c7792b2c918a4d5.
Report an issue: GitHub.