diff --git a/ponos/recipe.py b/ponos/recipe.py
index 42ef5b282bbeab15fa22335736b5781269cf791e..0daeff53911fac83a76af64671190e23d69d87ff 100644
--- a/ponos/recipe.py
+++ b/ponos/recipe.py
@@ -1,5 +1,6 @@
 import re
 from collections import namedtuple
+from uuid import UUID
 
 import yaml
 from django.core.validators import URLValidator
@@ -56,6 +57,10 @@ def validate_task(task, top_env):
 
     if "artifact" in task:
         assert isinstance(task["artifact"], str), "Task artifact should be a string"
+        try:
+            UUID(task["artifact"])
+        except (TypeError, ValueError):
+            raise AssertionError("Task artifact should be a valid UUID string")
 
     if "requires_gpu" in task:
         assert isinstance(
diff --git a/tests/server/test_recipe.py b/tests/server/test_recipe.py
new file mode 100644
index 0000000000000000000000000000000000000000..18ef2dbe9aaf879659cb2e4e71164b9248d30a45
--- /dev/null
+++ b/tests/server/test_recipe.py
@@ -0,0 +1,42 @@
+from textwrap import dedent
+
+from django.test import TestCase
+
+from ponos.recipe import parse_recipe
+
+# List of (broken recipe, expected AssertionError message) tuples
+ERROR_CASES = [
+    ("[]", "Recipe should be a dict"),
+    ("tasks: {}", "No tasks"),
+    ("tasks: [{image: lol}]", "Tasks should be a dict"),
+    ("tasks: {a: {}, '': {}}", "Tasks should have non-blank slugs"),
+    ("tasks: {a: []}", "Task should be a dict"),
+    ("tasks: {a: {}}", "Missing image"),
+    (
+        """
+    tasks:
+      lol:
+        image: blah
+        artifact: 42
+    """,
+        "Task artifact should be a string",
+    ),
+    (
+        """
+    tasks:
+      lol:
+        image: blah
+        artifact: philosophers_stone
+    """,
+        "Task artifact should be a valid UUID string",
+    ),
+]
+
+
+class TestRecipe(TestCase):
+    def test_recipe_errors(self):
+        for recipe, expected_message in ERROR_CASES:
+            with self.subTest(recipe=recipe), self.assertRaisesMessage(
+                AssertionError, expected_message
+            ):
+                parse_recipe(dedent(recipe))