diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index 7771802bc98bd051261fac91c6dc92f4d7f27a6a..846202885125b7e1f9611f815f6ce2f236187d04 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -266,6 +266,20 @@ class DynamicFormField extends VerySimpleModel {
         return $this->get('edit_mask') & 8;
     }
 
+    /**
+     * Used when updating the form via the admin panel. This represents
+     * validation on the form field template, not data entered into a form
+     * field of a custom form. The latter would be isValidEntry()
+     */
+    function isValid() {
+        if (count($this->errors()) || !parent::isValid())
+            return false;
+        if ($this->get('required') && !$this->get('name'))
+            $this->addError(
+                "Variable name is required for required fields", "name");
+        return count($this->errors()) == 0;
+    }
+
     function delete() {
         // Don't really delete form fields as that will screw up the data
         // model. Instead, just drop the association with the form which
diff --git a/include/class.forms.php b/include/class.forms.php
index 8bfe89fc6e361b6824d2c463d3b514e876fb0026..97c27e922a28690605cfc9ffb4c1bfc82a2158ff 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -183,6 +183,12 @@ class FormField {
     function errors() {
         return $this->_errors;
     }
+    function addError($message, $field=false) {
+        if ($field)
+            $this->_errors[$field] = $message;
+        else
+            $this->_errors[] = $message;
+    }
 
     function isValidEntry() {
         $this->validateEntry();
diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php
index 1685d6cac6c021693ebf843683dae0c8b0caed4d..b7b9e875f03958b305ff2fe7ded27fe53fceede8 100644
--- a/include/staff/dynamic-form.inc.php
+++ b/include/staff/dynamic-form.inc.php
@@ -100,7 +100,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         </tr>
     </thead>
     <tbody class="sortable-rows" data-sort="sort-">
-    <?php if ($form) foreach ($form->getFields() as $f) {
+    <?php if ($form) foreach ($form->getDynamicFields() as $f) {
         $id = $f->get('id');
         $deletable = !$f->isDeletable() ? 'disabled="disabled"' : '';
         $force_name = $f->isNameForced() ? 'disabled="disabled"' : '';
diff --git a/scp/forms.php b/scp/forms.php
index 5c0a2ad0481f53c013cc4cd509d778a91a0dd2ba..311207756652d6c1d560d79923a93bc16abc0c5b 100644
--- a/scp/forms.php
+++ b/scp/forms.php
@@ -40,9 +40,14 @@ if($_POST) {
                 }
                 if ($field->isValid())
                     $field->save();
+                else
+                    # notrans (not shown)
+                    $errors["field-$id"] = 'Field has validation errors';
                 // Keep track of the last sort number
                 $max_sort = max($max_sort, $field->get('sort'));
             }
+            if ($errors)
+                $errors['err'] = 'Unable to commit form. Check validation errors';
             break;
         case 'add':
             $form = DynamicForm::create(array(
@@ -94,7 +99,8 @@ if($_POST) {
                 $field->save();
         }
         // XXX: Move to an instrumented list that can handle this better
-        $form->_dfields = $form->_fields = null;
+        if (!$errors)
+            $form->_dfields = $form->_fields = null;
     }
 }