diff --git a/src/main/java/net/minestom/server/command/builder/Arguments.java b/src/main/java/net/minestom/server/command/builder/Arguments.java
index fed135523..e10f26ddc 100644
--- a/src/main/java/net/minestom/server/command/builder/Arguments.java
+++ b/src/main/java/net/minestom/server/command/builder/Arguments.java
@@ -21,6 +21,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Supplier;
 
 /**
  * @deprecated renamed to {@link CommandContext}
@@ -296,14 +297,17 @@ public class Arguments {
         this.args.clear();
     }
 
-    protected void retrieveDefaultValues(@Nullable Map<String, Object> defaultValuesMap) {
+    protected void retrieveDefaultValues(@Nullable Map<String, Supplier<Object>> defaultValuesMap) {
         if (defaultValuesMap == null)
             return;
 
-        for (Map.Entry<String, Object> entry : defaultValuesMap.entrySet()) {
+        for (Map.Entry<String, Supplier<Object>> entry : defaultValuesMap.entrySet()) {
             final String key = entry.getKey();
-            if (!args.containsKey(key))
-                this.args.put(key, entry.getValue());
+            if (!args.containsKey(key)) {
+                final var supplier = entry.getValue();
+                this.args.put(key, supplier.get());
+
+            }
         }
 
     }
diff --git a/src/main/java/net/minestom/server/command/builder/Command.java b/src/main/java/net/minestom/server/command/builder/Command.java
index 55ddaaea3..4933f70fd 100644
--- a/src/main/java/net/minestom/server/command/builder/Command.java
+++ b/src/main/java/net/minestom/server/command/builder/Command.java
@@ -13,6 +13,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.*;
+import java.util.function.Supplier;
 
 /**
  * Represents a command which has suggestion/auto-completion.
@@ -157,14 +158,14 @@ public class Command {
 
             // the 'args' array starts by all the required arguments, followed by the optional ones
             List<Argument<?>> requiredArguments = new ArrayList<>();
-            Map<String, Object> defaultValuesMap = new HashMap<>();
+            Map<String, Supplier<Object>> defaultValuesMap = new HashMap<>();
             boolean optionalBranch = false;
             int i = 0;
             for (Argument<?> argument : args) {
                 final boolean isLast = ++i == args.length;
                 if (argument.isOptional()) {
                     // Set default value
-                    defaultValuesMap.put(argument.getId(), argument.getDefaultValue());
+                    defaultValuesMap.put(argument.getId(), (Supplier<Object>) argument.getDefaultValue());
 
                     if (!optionalBranch && !requiredArguments.isEmpty()) {
                         // First optional argument, create a syntax with current cached arguments
diff --git a/src/main/java/net/minestom/server/command/builder/CommandDispatcher.java b/src/main/java/net/minestom/server/command/builder/CommandDispatcher.java
index 3212c0b5d..3cbfa0439 100644
--- a/src/main/java/net/minestom/server/command/builder/CommandDispatcher.java
+++ b/src/main/java/net/minestom/server/command/builder/CommandDispatcher.java
@@ -176,6 +176,7 @@ public class CommandDispatcher {
                     // Empty syntax found
                     final CommandSyntax syntax = optionalSyntax.get();
 
+                    parsedCommand.syntax = syntax;
                     parsedCommand.executor = syntax.getExecutor();
                     parsedCommand.context = new CommandContext(input);
 
diff --git a/src/main/java/net/minestom/server/command/builder/CommandSyntax.java b/src/main/java/net/minestom/server/command/builder/CommandSyntax.java
index c45fd7b9b..a9ee4238a 100644
--- a/src/main/java/net/minestom/server/command/builder/CommandSyntax.java
+++ b/src/main/java/net/minestom/server/command/builder/CommandSyntax.java
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
 import java.util.Map;
+import java.util.function.Supplier;
 
 /**
  * Represents a syntax in {@link Command}
@@ -18,14 +19,14 @@ public class CommandSyntax {
     private CommandCondition commandCondition;
     private CommandExecutor executor;
 
-    private final Map<String, Object> defaultValuesMap;
+    private final Map<String, Supplier<Object>> defaultValuesMap;
     private final Argument<?>[] args;
 
     private final boolean suggestion;
 
     protected CommandSyntax(@Nullable CommandCondition commandCondition,
                             @NotNull CommandExecutor commandExecutor,
-                            @Nullable Map<String, Object> defaultValuesMap,
+                            @Nullable Map<String, Supplier<Object>> defaultValuesMap,
                             @NotNull Argument<?>... args) {
         this.commandCondition = commandCondition;
         this.executor = commandExecutor;
@@ -85,7 +86,7 @@ public class CommandSyntax {
     }
 
     @Nullable
-    protected Map<String, Object> getDefaultValuesMap() {
+    protected Map<String, Supplier<Object>> getDefaultValuesMap() {
         return defaultValuesMap;
     }
 
diff --git a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java
index aedff3c1f..bc0514fcc 100644
--- a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java
+++ b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java
@@ -11,6 +11,8 @@ import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.function.Supplier;
+
 /**
  * An argument is meant to be parsed when added into a {@link Command}'s syntax with {@link Command#addSyntax(CommandExecutor, Argument[])}.
  * <p>
@@ -28,7 +30,7 @@ public abstract class Argument<T> {
 
     private ArgumentCallback callback;
 
-    private T defaultValue;
+    private Supplier<T> defaultValue;
 
     private SuggestionCallback suggestionCallback;
 
@@ -173,18 +175,13 @@ public abstract class Argument<T> {
         return defaultValue != null;
     }
 
-    /**
-     * Gets the default value of this argument.
-     *
-     * @return the argument default value, null if the argument is not optional
-     */
     @Nullable
-    public T getDefaultValue() {
+    public Supplier<T> getDefaultValue() {
         return defaultValue;
     }
 
     /**
-     * Sets the default value of the argument.
+     * Sets the default value supplier of the argument.
      * <p>
      * A non-null value means that the argument can be put at the end of a syntax
      * to act as an optional one.
@@ -193,11 +190,21 @@ public abstract class Argument<T> {
      * @return 'this' for chaining
      */
     @NotNull
-    public Argument<T> setDefaultValue(@Nullable T defaultValue) {
+    public Argument<T> setDefaultValue(@Nullable Supplier<T> defaultValue) {
         this.defaultValue = defaultValue;
         return this;
     }
 
+    /**
+     * @deprecated use {@link #setDefaultValue(Supplier)}
+     */
+    @NotNull
+    @Deprecated
+    public Argument<T> setDefaultValue(@Nullable T defaultValue) {
+        this.defaultValue = () -> defaultValue;
+        return this;
+    }
+
     @Nullable
     public SuggestionCallback getSuggestionCallback() {
         return suggestionCallback;