diff --git a/src/applications/diviner/atom/DivinerAtom.php b/src/applications/diviner/atom/DivinerAtom.php
index f7f8d2c4ac..93e24d5d03 100644
--- a/src/applications/diviner/atom/DivinerAtom.php
+++ b/src/applications/diviner/atom/DivinerAtom.php
@@ -1,436 +1,436 @@
 <?php
 
 final class DivinerAtom extends Phobject {
 
   const TYPE_ARTICLE   = 'article';
   const TYPE_CLASS     = 'class';
   const TYPE_FILE      = 'file';
   const TYPE_FUNCTION  = 'function';
   const TYPE_INTERFACE = 'interface';
   const TYPE_METHOD    = 'method';
 
   private $type;
   private $name;
   private $file;
   private $line;
   private $hash;
   private $contentRaw;
   private $length;
   private $language;
   private $docblockRaw;
   private $docblockText;
   private $docblockMeta;
   private $warnings = array();
   private $parent;
   private $parentHash;
   private $children = array();
   private $childHashes = array();
   private $context;
   private $extends = array();
   private $links = array();
   private $book;
   private $properties = array();
 
   /**
    * Returns a sorting key which imposes an unambiguous, stable order on atoms.
    */
   public function getSortKey() {
     return implode(
       "\0",
       array(
         $this->getBook(),
         $this->getType(),
         $this->getContext(),
         $this->getName(),
         $this->getFile(),
         sprintf('%08d', $this->getLine()),
       ));
   }
 
   public function setBook($book) {
     $this->book = $book;
     return $this;
   }
 
   public function getBook() {
     return $this->book;
   }
 
   public function setContext($context) {
     $this->context = $context;
     return $this;
   }
 
   public function getContext() {
     return $this->context;
   }
 
   public static function getAtomSerializationVersion() {
     return 2;
   }
 
   public function addWarning($warning) {
     $this->warnings[] = $warning;
     return $this;
   }
 
   public function getWarnings() {
     return $this->warnings;
   }
 
   public function setDocblockRaw($docblock_raw) {
     $this->docblockRaw = $docblock_raw;
 
     $parser = new PhutilDocblockParser();
     list($text, $meta) = $parser->parse($docblock_raw);
     $this->docblockText = $text;
     $this->docblockMeta = $meta;
 
     return $this;
   }
 
   public function getDocblockRaw() {
     return $this->docblockRaw;
   }
 
   public function getDocblockText() {
     if ($this->docblockText === null) {
       throw new PhutilInvalidStateException('setDocblockRaw');
     }
     return $this->docblockText;
   }
 
   public function getDocblockMeta() {
     if ($this->docblockMeta === null) {
       throw new PhutilInvalidStateException('setDocblockRaw');
     }
     return $this->docblockMeta;
   }
 
   public function getDocblockMetaValue($key, $default = null) {
     $meta = $this->getDocblockMeta();
     return idx($meta, $key, $default);
   }
 
   public function setDocblockMetaValue($key, $value) {
     $meta = $this->getDocblockMeta();
     $meta[$key] = $value;
     $this->docblockMeta = $meta;
     return $this;
   }
 
   public function setType($type) {
     $this->type = $type;
     return $this;
   }
 
   public function getType() {
     return $this->type;
   }
 
   public function setName($name) {
     $this->name = $name;
     return $this;
   }
 
   public function getName() {
     return $this->name;
   }
 
   public function setFile($file) {
     $this->file = $file;
     return $this;
   }
 
   public function getFile() {
     return $this->file;
   }
 
   public function setLine($line) {
     $this->line = $line;
     return $this;
   }
 
   public function getLine() {
     return $this->line;
   }
 
   public function setContentRaw($content_raw) {
     $this->contentRaw = $content_raw;
     return $this;
   }
 
   public function getContentRaw() {
     return $this->contentRaw;
   }
 
   public function setHash($hash) {
     $this->hash = $hash;
     return $this;
   }
 
   public function addLink(DivinerAtomRef $ref) {
     $this->links[] = $ref;
     return $this;
   }
 
   public function addExtends(DivinerAtomRef $ref) {
     $this->extends[] = $ref;
     return $this;
   }
 
   public function getLinkDictionaries() {
     return mpull($this->links, 'toDictionary');
   }
 
   public function getExtendsDictionaries() {
     return mpull($this->extends, 'toDictionary');
   }
 
   public function getExtends() {
     return $this->extends;
   }
 
   public function getHash() {
     if ($this->hash) {
       return $this->hash;
     }
 
     $parts = array(
       $this->getBook(),
       $this->getType(),
       $this->getName(),
       $this->getFile(),
       $this->getLine(),
       $this->getLength(),
       $this->getLanguage(),
       $this->getContentRaw(),
       $this->getDocblockRaw(),
       $this->getProperties(),
       $this->getChildHashes(),
       mpull($this->extends, 'toHash'),
       mpull($this->links, 'toHash'),
     );
 
     $this->hash = md5(serialize($parts)).'N';
     return $this->hash;
   }
 
   public function setLength($length) {
     $this->length = $length;
     return $this;
   }
 
   public function getLength() {
     return $this->length;
   }
 
   public function setLanguage($language) {
     $this->language = $language;
     return $this;
   }
 
   public function getLanguage() {
     return $this->language;
   }
 
   public function addChildHash($child_hash) {
     $this->childHashes[] = $child_hash;
     return $this;
   }
 
   public function getChildHashes() {
     if (!$this->childHashes && $this->children) {
       $this->childHashes = mpull($this->children, 'getHash');
     }
     return $this->childHashes;
   }
 
   public function setParentHash($parent_hash) {
     if ($this->parentHash) {
       throw new Exception(pht('Atom already has a parent!'));
     }
     $this->parentHash = $parent_hash;
     return $this;
   }
 
   public function hasParent() {
     return $this->parent || $this->parentHash;
   }
 
   public function setParent(DivinerAtom $atom) {
     if ($this->parentHash) {
       throw new Exception(pht('Parent hash has already been computed!'));
     }
     $this->parent = $atom;
     return $this;
   }
 
   public function getParentHash() {
     if ($this->parent && !$this->parentHash) {
       $this->parentHash = $this->parent->getHash();
     }
     return $this->parentHash;
   }
 
   public function addChild(DivinerAtom $atom) {
     if ($this->childHashes) {
       throw new Exception(pht('Child hashes have already been computed!'));
     }
 
     $atom->setParent($this);
     $this->children[] = $atom;
     return $this;
   }
 
   public function getURI() {
     $parts = array();
     $parts[] = phutil_escape_uri_path_component($this->getType());
     if ($this->getContext()) {
       $parts[] = phutil_escape_uri_path_component($this->getContext());
     }
     $parts[] = phutil_escape_uri_path_component($this->getName());
     $parts[] = null;
     return implode('/', $parts);
   }
 
   public function toDictionary() {
     // NOTE: If you change this format, bump the format version in
     // @{method:getAtomSerializationVersion}.
     return array(
       'book'        => $this->getBook(),
       'type'        => $this->getType(),
       'name'        => $this->getName(),
       'file'        => $this->getFile(),
       'line'        => $this->getLine(),
       'hash'        => $this->getHash(),
       'uri'         => $this->getURI(),
       'length'      => $this->getLength(),
       'context'     => $this->getContext(),
       'language'    => $this->getLanguage(),
       'docblockRaw' => $this->getDocblockRaw(),
       'warnings'    => $this->getWarnings(),
       'parentHash'  => $this->getParentHash(),
       'childHashes' => $this->getChildHashes(),
       'extends'     => $this->getExtendsDictionaries(),
       'links'       => $this->getLinkDictionaries(),
       'ref'         => $this->getRef()->toDictionary(),
       'properties'  => $this->getProperties(),
     );
   }
 
   public function getRef() {
     $title = null;
     if ($this->docblockMeta) {
       $title = $this->getDocblockMetaValue('title');
     }
 
     return id(new DivinerAtomRef())
       ->setBook($this->getBook())
       ->setContext($this->getContext())
       ->setType($this->getType())
       ->setName($this->getName())
       ->setTitle($title)
       ->setGroup($this->getProperty('group'));
   }
 
   public static function newFromDictionary(array $dictionary) {
     $atom = id(new DivinerAtom())
       ->setBook(idx($dictionary, 'book'))
       ->setType(idx($dictionary, 'type'))
       ->setName(idx($dictionary, 'name'))
       ->setFile(idx($dictionary, 'file'))
       ->setLine(idx($dictionary, 'line'))
       ->setHash(idx($dictionary, 'hash'))
       ->setLength(idx($dictionary, 'length'))
       ->setContext(idx($dictionary, 'context'))
       ->setLanguage(idx($dictionary, 'language'))
       ->setParentHash(idx($dictionary, 'parentHash'))
-      ->setDocblockRaw(idx($dictionary, 'docblockRaw'))
+      ->setDocblockRaw(coalesce(idx($dictionary, 'docblockRaw'), ''))
       ->setProperties(idx($dictionary, 'properties'));
 
     foreach (idx($dictionary, 'warnings', array()) as $warning) {
       $atom->addWarning($warning);
     }
 
     foreach (idx($dictionary, 'childHashes', array()) as $child) {
       $atom->addChildHash($child);
     }
 
     foreach (idx($dictionary, 'extends', array()) as $extends) {
       $atom->addExtends(DivinerAtomRef::newFromDictionary($extends));
     }
 
     return $atom;
   }
 
   public function getProperty($key, $default = null) {
     return idx($this->properties, $key, $default);
   }
 
   public function setProperty($key, $value) {
     $this->properties[$key] = $value;
     return $this;
   }
 
   public function getProperties() {
     return $this->properties;
   }
 
   public function setProperties(array $properties) {
     $this->properties = $properties;
     return $this;
   }
 
   public static function getThisAtomIsNotDocumentedString($type) {
     switch ($type) {
       case self::TYPE_ARTICLE:
         return pht('This article is not documented.');
       case self::TYPE_CLASS:
         return pht('This class is not documented.');
       case self::TYPE_FILE:
         return pht('This file is not documented.');
       case self::TYPE_FUNCTION:
         return pht('This function is not documented.');
       case self::TYPE_INTERFACE:
         return pht('This interface is not documented.');
       case self::TYPE_METHOD:
         return pht('This method is not documented.');
       default:
         phlog(pht("Need translation for '%s'.", $type));
         return pht('This %s is not documented.', $type);
     }
   }
 
   public static function getAllTypes() {
     return array(
       self::TYPE_ARTICLE,
       self::TYPE_CLASS,
       self::TYPE_FILE,
       self::TYPE_FUNCTION,
       self::TYPE_INTERFACE,
       self::TYPE_METHOD,
     );
   }
 
   public static function getAtomTypeNameString($type) {
     switch ($type) {
       case self::TYPE_ARTICLE:
         return pht('Article');
       case self::TYPE_CLASS:
         return pht('Class');
       case self::TYPE_FILE:
         return pht('File');
       case self::TYPE_FUNCTION:
         return pht('Function');
       case self::TYPE_INTERFACE:
         return pht('Interface');
       case self::TYPE_METHOD:
         return pht('Method');
       default:
         phlog(pht("Need translation for '%s'.", $type));
         return ucwords($type);
     }
   }
 
 }