Macros are indeed quite the bit of rope, but they're actually not that hard to tame. The problem is that when you forget to use gen-sym (to create unique symbols at macro expansion time) it will often work, but then suddenly do really weird things in the wrong context. My main beef with CL macros is that they're quite cumbersome to write, since there's no shortcuts for things like gen-sym out of the box. This is something that later lisps like Clojure fixed, although they have to provide these fixes by default, since they lack some of the more powerful and dangerous features listed below.

The worst bit of rope I ever personally saw was reader macros. These allowed you to essentially modify the grammar of the language on the fly, inserting functions into the lexer to handle unknown symbols at read time. This is exactly how the quote operator, which allows you to insert literal code without running it, works. Since this happened at run time, any reader macro you registered affected all files that were read later, and thus was build order dependent. If you wanted to use your reader macro in every file, you better load it first and hope it doesn't break any of your libraries.

CLOS, the standard OOP structure of CL was also full of foot guns. It's super impressive that they managed to add an OOP system to an existing language without breaking everything, but the design was .... dangerous. CLOS has some pretty weird rules around method routing, with the methods existing outside Objects and routing be handled by argument specificity. The moment you find yourself extending classes just to win the specificity race with another method you have gone too far and it's time to turn around and go back down whatever road you came up.

For the most part CLOS was fine, but you could design yourself into some really weird corners. The worst part about CLOS was the before, after, and around functions. These allowed you to add functions that wrapped your regular functions, possibly multiple times with order of execution being handled by similar specificity rules. The kicker was that every of these methods was responsible to call the magic "call-next-method" function, which continued the call chain down the stack. If an around method did not do this, the main method would never execute. It is super confusing to manually call a method, only for it to not execute or trigger your debugger, especially since you can register around methods on any method from any package.

Also, CL has a very weak definition of package privacy. Any public symbol, function or otherwise, is accessed externally with the form "package:symbol". But private symbols, those not explicitly exported, can be accessed with "package::symbol". Much like ruby's much maligned "send" method, there's nothing preventing sane programmers from staying way the hell away from private methods. But just like ruby's send method, that is a mighty tempting tool to leave laying around when deadlines loom and pressure is mounting.

Before I finish, a sibling comment mentioned the loop macro. This thing is absolutely insane, I personally stayed way away from it because I never really mastered it, and syntactically is didn't match anything else from CL. Here's a valid example from the "LOOP for Black Belts"[0] page.

(loop for i in *random*
counting (evenp i) into evens
counting (oddp i) into odds
summing i into total
maximizing i into max
minimizing i into min
finally (return (list min max total evens odds)))

While it sure is pretty, it's really jarring when you're working in CL. Where are the parens? How the heck does this parse? What is the runtime complexity of this thing? How do I figure out what magic keywords are available within this loop macro? It's maddening!

And before you ask, no symbols like "counting" are not already functions in the lisp standard. That would be far too easy. God help you if you have a loop call that needs to be modified just enough to make using loop unfeasible.

[0] http://www.gigamonkeys.com/book/loop-for-black-belts.html