The Nix language itself is the hardest part.
Let me disagree there, the language is trivial. It's just JSON-lookalike with expressions, with a lot of nice touches that make using it much easier than all the alternatives (e.g. sane multi-line string handling, lazy evaluation, default values, powerful key/value sets, etc.). The only real stumbling for me when first encountering it was realizing that functions can only take a single argument (which can be a key/value set) and that functions are literally just :
(e.g. (a: a + 5) 6 => 11). That's easily missed if you just look at a file without reading the documentation.
The thing that makes it hard is just the complexity of the actual package collection, your configuration contains literally your whole system, and it's not always obvious where to find the thing you need, since sometimes it's a plain package, sometimes it is a services.foobar.enable = true
and sometimes you have to fiddle with override or other package specific things. Knowing that
https://search.nixos.org/ exists is half the battle here.
There is also the lack of static typing that can lead to rather verbose error messages, but it's not like many other configuration formats have that either.