diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 3fc9bbc11b6291561971c647f75cd5ace566f400..820f4eb300210703af2901070480187d2b678471 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -1282,11 +1282,12 @@ int NodeResolver::addNode(std::string n_wanted, std::string n_alt,
 		if (m_ndef->getId(n_wanted, *content))
 			return NR_STATUS_SUCCESS;
 
-		if (n_alt == "")
+		if (n_alt == "" || !m_ndef->getId(n_alt, *content)) {
+			*content = c_fallback;
 			return NR_STATUS_FAILURE;
+		}
 
-		return m_ndef->getId(n_alt, *content) ?
-			NR_STATUS_SUCCESS : NR_STATUS_FAILURE;
+		return NR_STATUS_SUCCESS;
 	} else {
 		NodeResolveInfo *nfi = new NodeResolveInfo;
 		nfi->n_wanted   = n_wanted;
@@ -1378,7 +1379,7 @@ int NodeResolver::resolveNodes()
 				"resolve '" << nri->n_wanted;
 			if (nri->n_alt != "")
 				errorstream << "' and '" << nri->n_alt;
-			errorstream << "' to a content ID" << std::endl;
+			errorstream << "'" << std::endl;
 		}
 
 		delete nri;
@@ -1399,6 +1400,12 @@ int NodeResolver::resolveNodes()
 		m_ndef->getIds(name, idset);
 		for (it = idset.begin(); it != idset.end(); ++it)
 			output->push_back(*it);
+
+		if (idset.size() == 0) {
+			num_failed++;
+			errorstream << "NodeResolver::resolveNodes():  Failed to "
+				"resolve '" << name << "'" << std::endl;
+		}
 	}
 
 	//// Mark node registration as complete so future resolve
diff --git a/src/nodedef.h b/src/nodedef.h
index bd29b92b640d3f093acacaa13812aa18759e960d..489aefffddb0af0b53ac58af06932d5797e26187 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -293,20 +293,106 @@ struct NodeResolveInfo {
 #define NR_STATUS_PENDING 1
 #define NR_STATUS_SUCCESS 2
 
+/**
+	NodeResolver
+
+	NodeResolver attempts to resolve node names to content ID integers. If the
+	node registration phase has not yet finished at the time the resolution
+	request is placed, the request is marked as pending and added to an internal
+	queue.  The name resolution request is later satisfied by writing directly
+	to the output location when the node registration phase has been completed.
+
+	This is primarily intended to be used for objects registered during script
+	initialization (i.e. while nodes are being registered) that reference
+	particular nodes.
+*/
 class NodeResolver {
 public:
 	NodeResolver(INodeDefManager *ndef);
 	~NodeResolver();
 
+	/**
+		Add a request to resolve the node n_wanted and set *content to the
+		result, or alternatively, n_alt if n_wanted is not found.  If n_alt
+		cannot be found either, or has not been specified, *content is set
+		to c_fallback.
+
+		If node registration is complete, the request is finished immediately
+		and NR_STATUS_SUCCESS is returned (or NR_STATUS_FAILURE if no node can
+		be found).  Otherwise, NR_STATUS_PENDING is returned and the resolution
+		request is queued.
+
+		N.B.  If the memory in which content is located has been deallocated
+		before the pending request had been satisfied, cancelNode() must be
+		called.
+
+		@param n_wanted Name of node that is wanted.
+		@param n_alt Name of node in case n_wanted could not be found.  Blank
+			if no alternative node is desired.
+		@param c_fallback Content ID that content is set to in case of node
+			resolution failure (should be CONTENT_AIR, CONTENT_IGNORE, etc.)
+		@param content Pointer to content_t that receives the result of the
+			node name resolution.
+		@return Status of node resolution request.
+	*/
 	int addNode(std::string n_wanted, std::string n_alt,
 		content_t c_fallback, content_t *content);
+
+	/**
+		Add a request to resolve the node(s) specified by nodename.
+
+		If node registration is complete, the request is finished immediately
+		and NR_STATUS_SUCCESS is returned if at least one node is resolved; if
+		zero were resolved, NR_STATUS_FAILURE.  Otherwise, NR_STATUS_PENDING is
+		returned and the resolution request is queued.
+
+		N.B.  If the memory in which content_vec is located has been deallocated
+		before the pending request had been satisfied, cancelNodeList() must be
+		called.
+
+		@param nodename Name of node (or node group) to be resolved. 
+		@param content_vec Pointer to content_t vector onto which the results
+			are added.
+
+		@return Status of node resolution request.
+	*/
 	int addNodeList(const char *nodename, std::vector<content_t> *content_vec);
 
+	/**
+		Removes all pending requests from the resolution queue to be satisfied
+		to content.
+
+		@param content Location of the content ID for the request being
+			cancelled.
+		@return Number of pending requests cancelled.
+	*/
 	bool cancelNode(content_t *content);
+
+	/**
+		Removes all pending requests from the resolution queue to be satisfied
+		to content_vec.
+
+		@param content_vec Location of the content ID vector for requests being
+			cancelled.
+		@return Number of pending requests cancelled.
+	*/
 	int cancelNodeList(std::vector<content_t> *content_vec);
 
+	/**
+		Carries out all pending node resolution requests.  Call this when the
+		node registration phase has completed.
+
+		Internally marks node registration as complete.
+
+		@return Number of failed pending requests.
+	*/
 	int resolveNodes();
 
+	/**
+		Returns the status of the node registration phase.
+
+		@return Boolean of whether the registration phase is complete.
+	*/
 	bool isNodeRegFinished() { return m_is_node_registration_complete; }
 
 private: