{"record":{"id":"b65d9f4583c70c8c","repo":"nats-io/nats-server","slug":"store-is-not-set-up-to-for-delete","errorCode":null,"errorMessage":"store is not set up to for delete","messagePattern":"store is not set up to for delete","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/dirstore.go","lineNumber":456,"sourceCode":"\t\t\t\treturn false, err\n\t\t\t} else {\n\t\t\t\tstore.expiration.unTrack(i.publicKey)\n\t\t\t}\n\t\t}\n\t}\n\tif err := os.WriteFile(path, []byte(theJWT), defaultFilePerms); err != nil {\n\t\treturn false, err\n\t} else if store.expiration != nil {\n\t\tstore.expiration.track(publicKey, newHash, theJWT)\n\t}\n\treturn true, nil\n}\n\nfunc (store *DirJWTStore) delete(publicKey string) error {\n\tif store.readonly {\n\t\treturn fmt.Errorf(\"store is read-only\")\n\t} else if store.deleteType == NoDelete {\n\t\treturn fmt.Errorf(\"store is not set up to for delete\")\n\t}\n\tstore.Lock()\n\tdefer store.Unlock()\n\tname := store.pathForKey(publicKey)\n\tif store.deleteType == RenameDeleted {\n\t\tif err := os.Rename(name, name+\".deleted\"); err != nil {\n\t\t\tif os.IsNotExist(err) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t} else if err := os.Remove(name); err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\tstore.expiration.unTrack(publicKey)","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/dirstore.go#L438-L474","documentation":"DirJWTStore.delete refuses to run because the store was created with a deleteType of NoDelete, meaning deletion of JWT files was never enabled for this store directory. The nats-server only wires up on-disk deletion when the store is configured with RenameDeleted or FullDelete; NoDelete stores are intentionally immutable with respect to removal. This is a configuration mismatch, not data corruption.","triggerScenarios":"Calling delete (directly or via handleDeleteRequest, Pop, or unTrack) on a DirJWTStore whose NewDirJWTStore options set deleteType to NoDelete, e.g. a memory or read-path-only store built without a delete-enable option.","commonSituations":"Operators hitting the resolver's delete API on a store that was started without delete support; embedding the store in code (Pop/unTrack) and assuming deletion works by default; older configurations where deleteType was never set.","solutions":["Recreate/open the DirJWTStore with a delete-enabled deleteType (RenameDeleted or FullDelete) via the appropriate store option","If deletion should not be enabled, change the caller to stop issuing deletes on this store and handle the error gracefully","Check store.deleteType (or the config that produced it) before calling delete to fail fast"],"exampleFix":"// before\nstore, _ := NewDirJWTStore(dir, false, nil) // deleteType defaults to NoDelete\nstore.delete(publicKey) // error: store is not set up to for delete\n// after\nstore, _ := NewDirJWTStore(dir, false, nil, DeleteType(RenameDeleted))\nerr := store.delete(publicKey) // renames <file> to <file>.deleted","handlingStrategy":"validation","validationCode":"if store.deleteType == NoDelete {\n    return fmt.Errorf(\"store does not support delete\")\n}\nerr := store.delete(publicKey)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure the store with a delete-enabled DeleteType when delete APIs will be used","Check deleteType/capabilities before exposing delete endpoints","Document per-store capabilities in your service layer"],"tags":["jwt","store","configuration"],"backgroundTag":"store-delete-not-enabled","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}