nats-io/nats-server · error

store is not set up to for delete

Error message

store is not set up to for delete

What it means

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.

Source

Thrown at server/dirstore.go:456

				return false, err
			} else {
				store.expiration.unTrack(i.publicKey)
			}
		}
	}
	if err := os.WriteFile(path, []byte(theJWT), defaultFilePerms); err != nil {
		return false, err
	} else if store.expiration != nil {
		store.expiration.track(publicKey, newHash, theJWT)
	}
	return true, nil
}

func (store *DirJWTStore) delete(publicKey string) error {
	if store.readonly {
		return fmt.Errorf("store is read-only")
	} else if store.deleteType == NoDelete {
		return fmt.Errorf("store is not set up to for delete")
	}
	store.Lock()
	defer store.Unlock()
	name := store.pathForKey(publicKey)
	if store.deleteType == RenameDeleted {
		if err := os.Rename(name, name+".deleted"); err != nil {
			if os.IsNotExist(err) {
				return nil
			}
			return err
		}
	} else if err := os.Remove(name); err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}
	store.expiration.unTrack(publicKey)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Recreate/open the DirJWTStore with a delete-enabled deleteType (RenameDeleted or FullDelete) via the appropriate store option
  2. If deletion should not be enabled, change the caller to stop issuing deletes on this store and handle the error gracefully
  3. Check store.deleteType (or the config that produced it) before calling delete to fail fast

Example fix

// before
store, _ := NewDirJWTStore(dir, false, nil) // deleteType defaults to NoDelete
store.delete(publicKey) // error: store is not set up to for delete
// after
store, _ := NewDirJWTStore(dir, false, nil, DeleteType(RenameDeleted))
err := store.delete(publicKey) // renames <file> to <file>.deleted
Defensive patterns

Strategy: validation

Validate before calling

if store.deleteType == NoDelete {
    return fmt.Errorf("store does not support delete")
}
err := store.delete(publicKey)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/b65d9f4583c70c8c. Report an issue: GitHub.