diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java
index 0cbe39421..6105255c5 100644
--- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java
+++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java
@@ -25,6 +25,9 @@ import org.jetbrains.annotations.ApiStatus;
 import net.minecraft.SharedConstants;
 import net.minecraft.data.DataGenerator;
 import net.minecraft.data.DataProvider;
+import net.minecraft.registry.BuiltinRegistries;
+import net.minecraft.registry.ExperimentalRegistriesValidator;
+import net.minecraft.registry.RegistryBuilder;
 import net.minecraft.registry.RegistryWrapper;
 import net.minecraft.util.Identifier;
 
@@ -95,6 +98,20 @@ public final class FabricDataGenerator extends DataGenerator {
 		return strictValidation;
 	}
 
+	/**
+	 * Get a future returning the default registries produced by {@link BuiltinRegistries} and
+	 * {@link DataGeneratorEntrypoint#buildRegistry(RegistryBuilder)}.
+	 *
+	 * <p>Generally one does not need direct access to the registries, and instead can pass them directly to a
+	 * {@link DataProvider} by using {@link Pack#addProvider(Pack.RegistryDependentFactory)}. However, this method may
+	 * be useful when extending the vanilla registries (such as with {@link ExperimentalRegistriesValidator}).
+	 *
+	 * @return A future containing the builtin registries.
+	 */
+	public CompletableFuture<RegistryWrapper.WrapperLookup> getRegistries() {
+		return registriesFuture;
+	}
+
 	/**
 	 * @deprecated Please use {@link FabricDataGenerator#createPack()}
 	 */
diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java
index 3a00e7193..edee955b3 100644
--- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java
+++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java
@@ -45,11 +45,13 @@ import net.minecraft.registry.Registerable;
 import net.minecraft.registry.Registries;
 import net.minecraft.registry.RegistryBuilder;
 import net.minecraft.registry.RegistryKey;
+import net.minecraft.registry.RegistryLoader;
 import net.minecraft.registry.RegistryWrapper;
 import net.minecraft.util.Util;
 
 import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
 import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
+import net.fabricmc.fabric.api.event.registry.DynamicRegistries;
 import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition;
 import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions;
 import net.fabricmc.loader.api.FabricLoader;
@@ -176,7 +178,7 @@ public final class FabricDataGenHelper {
 			BuilderData(RegistryKey key) {
 				this.key = key;
 				this.bootstrapFunctions = new ArrayList<>();
-				this.lifecycle = null;
+				this.lifecycle = Lifecycle.stable();
 			}
 
 			void with(RegistryBuilder.RegistryInfo<?> registryInfo) {
@@ -197,6 +199,11 @@ public final class FabricDataGenHelper {
 
 		Map<RegistryKey<?>, BuilderData> builderDataMap = new HashMap<>();
 
+		// Ensure all dynamic registries are present.
+		for (RegistryLoader.Entry<?> key : DynamicRegistries.getDynamicRegistries()) {
+			builderDataMap.computeIfAbsent(key.key(), BuilderData::new);
+		}
+
 		for (RegistryBuilder builder : builders) {
 			for (RegistryBuilder.RegistryInfo<?> info : builder.registries) {
 				builderDataMap.computeIfAbsent(info.key(), BuilderData::new)
diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java
index b367cc057..bdb921f38 100644
--- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java
+++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java
@@ -56,6 +56,10 @@ public class DataGeneratorTestContent implements ModInitializer {
 			TEST_DATAGEN_DYNAMIC_REGISTRY_KEY,
 			new Identifier(MOD_ID, "tiny_potato")
 	);
+	public static final RegistryKey<TestDatagenObject> TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY = RegistryKey.of(
+			TEST_DATAGEN_DYNAMIC_REGISTRY_KEY,
+			new Identifier(MOD_ID, "tinier_potato")
+	);
 	// Empty registry
 	public static final RegistryKey<Registry<TestDatagenObject>> TEST_DATAGEN_DYNAMIC_EMPTY_REGISTRY_KEY =
 			RegistryKey.ofRegistry(new Identifier("fabric", "test_datagen_dynamic_empty"));
diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
index 77b2f375c..a14c37ac4 100644
--- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
+++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
@@ -24,6 +24,7 @@ import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.MOD_ID;
 import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_BLOCK;
 import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_ITEM_GROUP;
 import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DATAGEN_DYNAMIC_REGISTRY_KEY;
+import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY;
 import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DYNAMIC_REGISTRY_ITEM_KEY;
 
 import java.io.IOException;
@@ -63,6 +64,7 @@ import net.minecraft.loot.entry.ItemEntry;
 import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
 import net.minecraft.recipe.Ingredient;
 import net.minecraft.recipe.book.RecipeCategory;
+import net.minecraft.registry.ExperimentalRegistriesValidator;
 import net.minecraft.registry.Registerable;
 import net.minecraft.registry.Registries;
 import net.minecraft.registry.RegistryBuilder;
@@ -139,6 +141,14 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
 				throw new RuntimeException(e);
 			}
 		}
+
+		FabricDataGenerator.Pack extraPack = dataGenerator.createBuiltinResourcePack(new Identifier(MOD_ID, "extra"));
+		CompletableFuture<RegistryWrapper.WrapperLookup> extraRegistries = ExperimentalRegistriesValidator.validate(dataGenerator.getRegistries(), new RegistryBuilder()
+				.addRegistry(TEST_DATAGEN_DYNAMIC_REGISTRY_KEY, c ->
+						c.register(TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY, new DataGeneratorTestContent.TestDatagenObject(":tiny_potato:"))
+				)
+		).thenApply(RegistryBuilder.FullPatchesRegistriesPair::full);
+		extraPack.addProvider((FabricDataOutput out) -> new TestExtraDynamicRegistryProvider(out, extraRegistries));
 	}
 
 	@Override
@@ -432,6 +442,25 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
 		}
 	}
 
+	/**
+	 * Test generating files for a patched/extended dynamic registry.
+	 */
+	private static class TestExtraDynamicRegistryProvider extends FabricDynamicRegistryProvider {
+		TestExtraDynamicRegistryProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
+			super(output, registriesFuture);
+		}
+
+		@Override
+		protected void configure(RegistryWrapper.WrapperLookup registries, Entries entries) {
+			entries.add(registries.getWrapperOrThrow(TEST_DATAGEN_DYNAMIC_REGISTRY_KEY), TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY);
+		}
+
+		@Override
+		public String getName() {
+			return "Test Dynamic Registry";
+		}
+	}
+
 	private static class TestPredicateProvider extends FabricCodecDataProvider<LootCondition> {
 		private TestPredicateProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
 			super(dataOutput, registriesFuture, DataOutput.OutputType.DATA_PACK, "predicates", LootCondition.CODEC);
diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java
new file mode 100644
index 000000000..e59c36f37
--- /dev/null
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.mixin.registry.sync;
+
+import java.util.List;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+import net.minecraft.registry.ExperimentalRegistriesValidator;
+import net.minecraft.registry.RegistryLoader;
+
+import net.fabricmc.fabric.api.event.registry.DynamicRegistries;
+
+@Mixin(ExperimentalRegistriesValidator.class)
+class ExperimentalRegistriesValidatorMixin {
+	@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/registry/RegistryLoader;DYNAMIC_REGISTRIES:Ljava/util/List;"), method = "method_54839")
+	private static List<RegistryLoader.Entry<?>> getDynamicRegistries() {
+		// Register cloners for all dynamic registries.
+		return DynamicRegistries.getDynamicRegistries();
+	}
+}
diff --git a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
index 36ddad626..c3e629e5a 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
@@ -6,6 +6,7 @@
     "BootstrapMixin",
     "ChunkSerializerMixin",
     "DebugChunkGeneratorAccessor",
+    "ExperimentalRegistriesValidatorMixin",
     "IdListMixin",
     "MinecraftServerMixin",
     "RegistriesAccessor",