diff --git a/gradle.properties b/gradle.properties
index 39e84f663..43d5b46c3 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,7 +17,7 @@ neoforge_version=21.1.42
 parchment_mc_version=1.21
 parchment_mapping_version=2024.07.28
 rhino_version=2101.2.5-build.54
-tiny_server_version=1.0.0-build.16
+tiny_server_version=1.0.0-build.18
 gif_lib_version=1.7
 
 architectury_version=13.0.6
diff --git a/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java b/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java
index 78dd14fc0..1dda8f8c0 100644
--- a/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java
+++ b/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java
@@ -10,11 +10,15 @@
 import com.mojang.serialization.JsonOps;
 import dev.latvian.mods.kubejs.util.JsonUtils;
 import dev.latvian.mods.kubejs.util.UtilsJS;
+import dev.latvian.mods.rhino.type.EnumTypeInfo;
+import dev.latvian.mods.rhino.type.TypeInfo;
 import io.netty.buffer.ByteBuf;
+import net.minecraft.core.Registry;
 import net.minecraft.network.RegistryFriendlyByteBuf;
 import net.minecraft.network.Utf8String;
 import net.minecraft.network.codec.ByteBufCodecs;
 import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.resources.ResourceKey;
 import net.minecraft.resources.ResourceLocation;
 import net.minecraft.util.StringRepresentable;
 import net.minecraft.util.valueproviders.IntProvider;
@@ -61,6 +65,30 @@ public void encode(ByteBuf buffer, @Nullable JsonElement value) {
 		}
 	};
 
+	Codec<Class<?>> ENUM_CLASS_CODEC = Codec.STRING.flatXmap(str -> {
+		try {
+			var c = Class.forName(str);
+
+			if (!c.isEnum()) {
+				return DataResult.error(() -> "Class '" + str + "' is not an enum");
+			}
+
+			return DataResult.success(c);
+		} catch (ClassNotFoundException e) {
+			return DataResult.error(() -> "Could not find enum class: " + str);
+		}
+	}, c -> DataResult.success(c.getName()));
+
+	Codec<EnumTypeInfo> ENUM_TYPE_INFO_CODEC = ENUM_CLASS_CODEC.flatXmap(c -> {
+		if (TypeInfo.of(c) instanceof EnumTypeInfo info) {
+			return DataResult.success(info);
+		} else {
+			return DataResult.error(() -> "Class " + c.getTypeName() + " is not an enum!");
+		}
+	}, info -> DataResult.success(info.asClass()));
+
+	Codec<ResourceKey<? extends Registry<?>>> REGISTRY_KEY = ResourceLocation.CODEC.xmap(ResourceKey::createRegistryKey, ResourceKey::location);
+
 	static <E> Codec<E> stringResolverCodec(Function<E, String> toStringFunction, Function<String, E> fromStringFunction) {
 		return Codec.STRING.flatXmap(str -> Optional.ofNullable(fromStringFunction.apply(str))
 				.map(DataResult::success)
diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java b/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java
index 0996a0ab9..f51aeba80 100644
--- a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java
+++ b/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java
@@ -7,6 +7,7 @@
 import com.mojang.serialization.DynamicOps;
 import com.mojang.serialization.JsonOps;
 import dev.latvian.mods.kubejs.component.DataComponentWrapper;
+import dev.latvian.mods.kubejs.error.KubeRuntimeException;
 import dev.latvian.mods.kubejs.ingredient.RegExIngredient;
 import dev.latvian.mods.kubejs.util.ID;
 import dev.latvian.mods.kubejs.util.Lazy;
@@ -89,8 +90,8 @@ static ItemStack wrap(RegistryAccessContainer registries, @Nullable Object o) {
 			return ItemStack.EMPTY;
 		} else if (o instanceof ItemStack stack) {
 			return stack.isEmpty() ? ItemStack.EMPTY : stack;
-		} else if (o instanceof Ingredient ingr) {
-			return ingr.kjs$getFirst();
+		} else if (o instanceof Ingredient) {
+			throw new KubeRuntimeException("Use .first of an ingredient to get its ItemStack!");
 		} else if (o instanceof ResourceLocation id) {
 			var item = BuiltInRegistries.ITEM.get(id);
 
diff --git a/src/main/java/dev/latvian/mods/kubejs/script/TypeWrapperRegistry.java b/src/main/java/dev/latvian/mods/kubejs/script/TypeWrapperRegistry.java
index a4d5ef471..4fc2f3431 100644
--- a/src/main/java/dev/latvian/mods/kubejs/script/TypeWrapperRegistry.java
+++ b/src/main/java/dev/latvian/mods/kubejs/script/TypeWrapperRegistry.java
@@ -3,6 +3,7 @@
 import com.mojang.serialization.Codec;
 import com.mojang.serialization.MapCodec;
 import dev.latvian.mods.kubejs.KubeJSCodecs;
+import dev.latvian.mods.kubejs.error.KubeRuntimeException;
 import dev.latvian.mods.kubejs.util.Cast;
 import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
 import dev.latvian.mods.rhino.Context;
@@ -54,7 +55,13 @@ public <T> void register(Class<T> target, ContextFromFunction<T> factory) {
 	}
 
 	public <T> void register(Class<T> target, RegistriesFromFunction<T> factory) {
-		typeWrappers.register(target, (cx, from, t) -> factory.apply(RegistryAccessContainer.of(cx), from));
+		typeWrappers.register(target, (cx, from, t) -> {
+			try {
+				return factory.apply(RegistryAccessContainer.of(cx), from);
+			} catch (KubeRuntimeException ex) {
+				throw ex.source(SourceLine.of(cx));
+			}
+		});
 	}
 
 	public <T> void register(Class<T> target, TypeWrapperValidator validator, DirectTypeWrapperFactory<T> factory) {