IMHO, the worst part of Drupal is having to learn the API. The core developers are constantly refactoring the heart of Drupal, which is a good thing overall. But it makes it very difficult for the average developer to keep up with the API. Major version releases prior to 4.7 required a developer to make relatively few changes to his module to make it compatible with the new release. 4.7, on the other hand, requires pretty much a complete rewrite of a given 4.6 module.
I'm not sure how it happened, but today I noticed that Drupal's menus were behaving very oddly. After upgrading to Drupal 6 and installing several additional modules, I noticed duplicate menu entries as well as other disturbing oddities. Items I was placing into the menu were not showing up. Menu items that I moved around were apparently saved but they did not appear properly in a dropdown context.
I was just working on a client site and had an epiphany as to why working with Drupal continues to be a frustrating experience for me.
As flexible and powerful as Drupal truly is, there is still an unacceptable level of non-determinism involved in working with Drupal whether it be in working with existing modules, theming or doing custom development.
Developers are all familiar with the default behavior of the drupal menu systems "local tasks" (aka tabs). These appear throughout most Drupal sites, primarily in the administration area, but also on other pages like the user profile.
Generally, developers are pretty good about creating logical local tasks, meaning only those menu items which logically live under another menu item (like view, edit, revisions, workflow, etc... live under the node/% menu item).
Now this one is pretty annoying to.
I'm writing a module that imports data into nodes. Sometimes this data has already been imported, and I only want to update existing rows with changes, if any.
After pulling in a row of data from the import file, I see if it already exists as a node in my database. If it does, I grab the node ID and load the existing node:$node = node_load($existing_nid);
I then do some magical stuff and save the node using the standard: