I'd say the opposite is actually true. Often generic code is clearer and less error prone that non-generic code. This is because generic code reduces the number of assumptions you make (e.g. if you can't know the actual type of the elements of a container, there are fewer operations you can apply to them. A function that concatenates two lists cannot accidentally try adding 1 to each element, because it doesn't know whether the elements are numbers. Hence, a whole class of mistakes is eliminated before you get the chance to commit them).
For example, (barring side-effects for simplicity) there is one and only one possible implementation for a function with signature:
f: T -> T
Where T is a generic type. Contrast this with:
g: Int -> Int
which has many implementations, many of them possibly not what you intended. If what you intended was the identity function for integers, better use f, because it has fewer possible implementations than g. It's even easier for the reader to understand: since f doesn't mention integers, there's no point in checking whether it does any operation with them. Of course this is a trivial example, but the same point applies to more complex functions.