"Too many open files" when the Gradle cache is persisted via impermanence

Hi, using NixOS I’m unable to build a fairly complex Android Studio project due to the following error:

  /home/user/.gradle/caches/transforms-3/5733630caa7698f873e3b6cb13dedb97/transformed/exifinterface-1.3.3-api.jar: Too many open files

This repeats for lots of different dependencies.

I found a few posts here already, but they are either specific to nixos-rebuild (which works fine for me) and/or the solutions don’t work for me.

What I’ve tried:

boot.kernel.sysctl = { "fs.file-max" = 524288; };

security.pam.loginLimits = [
  {
    domain = "*";
    type = "-";
    item = "nofile";
    value = "524288";
  }
];

fileSystems."/" = {
  device = "none";
  fsType = "tmpfs";
  options = ["defaults" "size=12G" "mode=755" "nr_inodes=1M"];
};
 
fileSystems."/home/user" = {
  device = "none";
  fsType = "tmpfs";
  options = ["defaults" "size=4G" "mode=777" "nr_inodes=1M"];
};

Also, ulimit -n outputs 524288.

What’s worth mentioning is that I’m using impermanence, and the Gradle cache directory is persisted:

persistence."/nix/persist/home/user".directories = [
  ".gradle"
]

Always tried rebooting inbetween testing the configurations, just to be sure.

Any idea on what the issue could be?

There are no issues when I remove ~/.gradle from the list of persisted directories, so it must be connected to that.
But I cannot figure out what exactly causes it to break.

Same thing with impermanence and sbt.

I’ve found this: Compiling Rust projects in a bind mount causes a "Too many open files" error · Issue #206 · nix-community/impermanence · GitHub.

I’ve fixed it by adding the method = "symlink":

{ impermanence, ... }: {
  imports = [ impermanence ];
  home.persistence."/nix/persist/home/igor" = {
    directories = [ { directory = ".cache/coursier"; method = "symlink"; } ];
    allowOther = true;
  };
}

Not sure if allowOther = true; is needed, I’ve added long time before, and it was just there.

You might want to use environment.persistence rather than home.persistence because the former avoids fuse entirely and is quite noticeably faster. There’s an option that has identical functionality and API to the latter but uses bind mounts (and is defined in system config). See my comment in a related GitHub issue for the exact conversion

2 Likes

Alright, thank you all for the suggestions.

Using method = "symlink"; unfortunately didn’t work for me either:

Reason: java.lang.RuntimeException: Could not create parent directory for lock file /home/paul/.gradle/wrapper/dists/gradle-8.7-bin/bhs2wmbdwecv87pi65oeuq5iu/gradle-8.7-bin.zip.lck

Please ensure Android Studio can write to the specified Gradle wrapper distribution directory.
You can also change Gradle home directory in Gradle Settings.

However, I am now using the second suggested approach and haven’t had any issues since:

environment.persistence."/nix/persist".users.[USER].directories = [
  ".gradle"
];

Edit: Nevermind, the error just appeared again when syncing a larger project…

Edit2: After another reboot, I was able to do some development work without this issue appearing.
I will need to do some more testing.