diff --git a/include/class.queue.php b/include/class.queue.php
index 49005516da7ed4b71c2b44c89e6865d5d4350903..4180162d566ee09abf694bd9d3982f983c6edda8 100644
--- a/include/class.queue.php
+++ b/include/class.queue.php
@@ -749,8 +749,8 @@ class CustomQueue extends VerySimpleModel {
         if (!$this->id)
             return;
 
-        $path = $this->parent ? $this->parent->getPath() : '';
-        return $path . "/{$this->id}";
+        $path = $this->parent ? $this->parent->buildPath() : '';
+        return rtrim($path, "/") . "/{$this->id}/";
     }
 
     function getFullName() {
@@ -800,6 +800,14 @@ class CustomQueue extends VerySimpleModel {
         if ($this->parent_id && !$this->parent)
             $errors['parent_id'] = __('Select a valid queue');
 
+        // Try to avoid infinite recursion determining ancestry
+        if ($this->parent_id && isset($this->id)) {
+            $P = $this;
+            while ($P = $P->parent)
+                if ($P->parent_id == $this->id)
+                    $errors['parent_id'] = __('Cannot be a descendent of itself');
+        }
+
         // Configure quick filter options
         $this->filter = $vars['filter'];
         if ($vars['sort_id']) {
@@ -925,17 +933,29 @@ class CustomQueue extends VerySimpleModel {
     }
 
     function save($refetch=false) {
-        $wasnew = !isset($this->id);
+        $nopath = !isset($this->path);
+        $path_changed = isset($this->dirty['parent_id']);
 
         if ($this->dirty)
             $this->updated = SqlFunction::NOW();
         if (!($rv = parent::save($refetch || $this->dirty)))
             return $rv;
 
-        if ($wasnew) {
+        if ($nopath) {
             $this->path = $this->buildPath();
             $this->save();
         }
+        if ($path_changed) {
+            $this->children->reset();
+            $move_children = function($q) use (&$move_children) {
+                foreach ($q->children as $qq) {
+                    $qq->path = $qq->buildPath();
+                    $qq->save();
+                    $move_children($qq);
+                }
+            };
+            $move_children($this);
+        }
         return $this->columns->saveAll()
             && $this->sorts->saveAll();
     }
diff --git a/include/staff/queue.inc.php b/include/staff/queue.inc.php
index 75a5edf56074142bbf7d4d4358623e870569ae1a..53afb43d5efbbcbdbd8754c2a9ddfde70e497b0e 100644
--- a/include/staff/queue.inc.php
+++ b/include/staff/queue.inc.php
@@ -89,8 +89,11 @@ else {
           == <?php echo $queue->parent_id ?: 0; ?>);">
           <option value="0">— <?php echo __('Top-Level Queue'); ?> —</option>
 <?php foreach (CustomQueue::queues() as $cq) {
-        if ($cq->getId() == $queue->getId())
-          continue;
+        // Queue cannot be a descendent of itself
+        if ($cq->id == $queue->id)
+            continue;
+        if (strpos($cq->path, "/{$queue->id}/") !== false)
+            continue;
 ?>
           <option value="<?php echo $cq->id; ?>"
             <?php if ($cq->getId() == $queue->parent_id) echo 'selected="selected"'; ?>