Problem creating path alias in code
Inspecting the differences in the node table, I noticed that the node created by my code had an empty language field. Updating this to "und" fixed the node alias.

This makes sense, because path_save() defaults to LANGUAGE_NONE (i.e. "und").

I had assumed that node_prepare would do likewise, but it does not.

So the solution is to set $node-&gt;language = LANGUAGE_NONE; at the point of creation.

Also, this is an easier way to create the alias...

$node-&gt;path = array('alias' =&gt; $path, 'pathauto' =&gt; FALSE);