diff --git a/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
index 539bdffa6..f2cfc5151 100644
--- a/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
+++ b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
@@ -1,341 +1,345 @@
 <?php
 
 final class PhabricatorOwnersPackageTransactionEditor
   extends PhabricatorApplicationTransactionEditor {
 
   public function getEditorApplicationClass() {
     return 'PhabricatorOwnersApplication';
   }
 
   public function getEditorObjectsDescription() {
     return pht('Owners Packages');
   }
 
   public function getTransactionTypes() {
     $types = parent::getTransactionTypes();
 
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_NAME;
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_OWNERS;
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_AUDITING;
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION;
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_PATHS;
     $types[] = PhabricatorOwnersPackageTransaction::TYPE_STATUS;
 
     return $types;
   }
 
   protected function getCustomTransactionOldValue(
     PhabricatorLiskDAO $object,
     PhabricatorApplicationTransaction $xaction) {
 
     switch ($xaction->getTransactionType()) {
       case PhabricatorOwnersPackageTransaction::TYPE_NAME:
         return $object->getName();
       case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
         $phids = mpull($object->getOwners(), 'getUserPHID');
         $phids = array_values($phids);
         return $phids;
       case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
         return (int)$object->getAuditingEnabled();
       case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
         return $object->getDescription();
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
         $paths = $object->getPaths();
         return mpull($paths, 'getRef');
       case PhabricatorOwnersPackageTransaction::TYPE_STATUS:
         return $object->getStatus();
     }
   }
 
   protected function getCustomTransactionNewValue(
     PhabricatorLiskDAO $object,
     PhabricatorApplicationTransaction $xaction) {
 
     switch ($xaction->getTransactionType()) {
       case PhabricatorOwnersPackageTransaction::TYPE_NAME:
       case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
       case PhabricatorOwnersPackageTransaction::TYPE_STATUS:
         return $xaction->getNewValue();
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
         $new = $xaction->getNewValue();
         foreach ($new as $key => $info) {
           $new[$key]['excluded'] = (int)idx($info, 'excluded');
         }
         return $new;
       case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
         return (int)$xaction->getNewValue();
       case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
         $phids = $xaction->getNewValue();
         $phids = array_unique($phids);
         $phids = array_values($phids);
         return $phids;
     }
   }
 
   protected function transactionHasEffect(
     PhabricatorLiskDAO $object,
     PhabricatorApplicationTransaction $xaction) {
 
     switch ($xaction->getTransactionType()) {
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
         $old = $xaction->getOldValue();
         $new = $xaction->getNewValue();
 
         $diffs = PhabricatorOwnersPath::getTransactionValueChanges($old, $new);
         list($rem, $add) = $diffs;
 
         return ($rem || $add);
     }
 
     return parent::transactionHasEffect($object, $xaction);
   }
 
   protected function applyCustomInternalTransaction(
     PhabricatorLiskDAO $object,
     PhabricatorApplicationTransaction $xaction) {
 
     switch ($xaction->getTransactionType()) {
       case PhabricatorOwnersPackageTransaction::TYPE_NAME:
         $object->setName($xaction->getNewValue());
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
         $object->setDescription($xaction->getNewValue());
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
         $object->setAuditingEnabled($xaction->getNewValue());
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_STATUS:
         $object->setStatus($xaction->getNewValue());
         return;
     }
 
     return parent::applyCustomInternalTransaction($object, $xaction);
   }
 
   protected function applyCustomExternalTransaction(
     PhabricatorLiskDAO $object,
     PhabricatorApplicationTransaction $xaction) {
 
     switch ($xaction->getTransactionType()) {
       case PhabricatorOwnersPackageTransaction::TYPE_NAME:
       case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
       case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
       case PhabricatorOwnersPackageTransaction::TYPE_STATUS:
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
         $old = $xaction->getOldValue();
         $new = $xaction->getNewValue();
 
         $owners = $object->getOwners();
         $owners = mpull($owners, null, 'getUserPHID');
 
         $rem = array_diff($old, $new);
         foreach ($rem as $phid) {
           if (isset($owners[$phid])) {
             $owners[$phid]->delete();
             unset($owners[$phid]);
           }
         }
 
         $add = array_diff($new, $old);
         foreach ($add as $phid) {
           $owners[$phid] = id(new PhabricatorOwnersOwner())
             ->setPackageID($object->getID())
             ->setUserPHID($phid)
             ->save();
         }
 
         // TODO: Attach owners here
         return;
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
         $old = $xaction->getOldValue();
         $new = $xaction->getNewValue();
 
         $paths = $object->getPaths();
 
         $diffs = PhabricatorOwnersPath::getTransactionValueChanges($old, $new);
         list($rem, $add) = $diffs;
 
         $set = PhabricatorOwnersPath::getSetFromTransactionValue($rem);
         foreach ($paths as $path) {
           $ref = $path->getRef();
           if (PhabricatorOwnersPath::isRefInSet($ref, $set)) {
             $path->delete();
           }
         }
 
         foreach ($add as $ref) {
           $path = PhabricatorOwnersPath::newFromRef($ref)
             ->setPackageID($object->getID())
             ->save();
         }
 
         return;
     }
 
     return parent::applyCustomExternalTransaction($object, $xaction);
   }
 
   protected function validateTransaction(
     PhabricatorLiskDAO $object,
     $type,
     array $xactions) {
 
     $errors = parent::validateTransaction($object, $type, $xactions);
 
     switch ($type) {
       case PhabricatorOwnersPackageTransaction::TYPE_NAME:
         $missing = $this->validateIsEmptyTextField(
           $object->getName(),
           $xactions);
 
         if ($missing) {
           $error = new PhabricatorApplicationTransactionValidationError(
             $type,
             pht('Required'),
             pht('Package name is required.'),
             nonempty(last($xactions), null));
 
           $error->setIsMissingFieldError(true);
           $errors[] = $error;
         }
         break;
       case PhabricatorOwnersPackageTransaction::TYPE_PATHS:
+        if (!$xactions) {
+          continue;
+        }
+
         $old = mpull($object->getPaths(), 'getRef');
         foreach ($xactions as $xaction) {
           $new = $xaction->getNewValue();
 
           // Check that we have a list of paths.
           if (!is_array($new)) {
             $errors[] = new PhabricatorApplicationTransactionValidationError(
               $type,
               pht('Invalid'),
               pht('Path specification must be a list of paths.'),
               $xaction);
             continue;
           }
 
           // Check that each item in the list is formatted properly.
           $type_exception = null;
           foreach ($new as $key => $value) {
             try {
               PhutilTypeSpec::checkMap(
                 $value,
                 array(
                   'repositoryPHID' => 'string',
                   'path' => 'string',
                   'excluded' => 'optional wild',
                 ));
             } catch (PhutilTypeCheckException $ex) {
               $errors[] = new PhabricatorApplicationTransactionValidationError(
                 $type,
                 pht('Invalid'),
                 pht(
                   'Path specification list contains invalid value '.
                   'in key "%s": %s.',
                   $key,
                   $ex->getMessage()),
                 $xaction);
               $type_exception = $ex;
             }
           }
 
           if ($type_exception) {
             continue;
           }
 
           // Check that any new paths reference legitimate repositories which
           // the viewer has permission to see.
           list($rem, $add) = PhabricatorOwnersPath::getTransactionValueChanges(
             $old,
             $new);
 
           if ($add) {
             $repository_phids = ipull($add, 'repositoryPHID');
 
             $repositories = id(new PhabricatorRepositoryQuery())
               ->setViewer($this->getActor())
               ->withPHIDs($repository_phids)
               ->execute();
             $repositories = mpull($repositories, null, 'getPHID');
 
             foreach ($add as $ref) {
               $repository_phid = $ref['repositoryPHID'];
               if (isset($repositories[$repository_phid])) {
                 continue;
               }
 
               $errors[] = new PhabricatorApplicationTransactionValidationError(
                 $type,
                 pht('Invalid'),
                 pht(
                   'Path specification list references repository PHID "%s", '.
                   'but that is not a valid, visible repository.',
                   $repository_phid));
             }
           }
         }
         break;
     }
 
     return $errors;
   }
 
   protected function shouldSendMail(
     PhabricatorLiskDAO $object,
     array $xactions) {
     return true;
   }
 
   protected function getMailSubjectPrefix() {
     return PhabricatorEnv::getEnvConfig('metamta.package.subject-prefix');
   }
 
   protected function getMailTo(PhabricatorLiskDAO $object) {
     return array(
       $this->requireActor()->getPHID(),
     );
   }
 
   protected function getMailCC(PhabricatorLiskDAO $object) {
     return mpull($object->getOwners(), 'getUserPHID');
   }
 
   protected function buildReplyHandler(PhabricatorLiskDAO $object) {
     return id(new OwnersPackageReplyHandler())
       ->setMailReceiver($object);
   }
 
   protected function buildMailTemplate(PhabricatorLiskDAO $object) {
     $id = $object->getID();
     $name = $object->getName();
 
     return id(new PhabricatorMetaMTAMail())
       ->setSubject($name)
       ->addHeader('Thread-Topic', $object->getPHID());
   }
 
   protected function buildMailBody(
     PhabricatorLiskDAO $object,
     array $xactions) {
 
     $body = parent::buildMailBody($object, $xactions);
 
     $detail_uri = PhabricatorEnv::getProductionURI(
       '/owners/package/'.$object->getID().'/');
 
     $body->addLinkSection(
       pht('PACKAGE DETAIL'),
       $detail_uri);
 
     return $body;
   }
 
   protected function supportsSearch() {
     return true;
   }
 
 }