ipfs/kubo · error

error setting ulimit without hard limit: %w

Error message

error setting ulimit without hard limit: %w

What it means

ManageFdLimit tried to raise the process file-descriptor limit. After the first attempt to set both soft and hard limits failed with EPERM (no privilege), it fell back to raising only the soft limit while keeping the current hard limit, and that fallback call to setLimit also failed. The original OS error is wrapped, so inspect it with errors.Is/errors.As for the underlying cause.

Source

Thrown at cmd/ipfs/util/ulimit.go:85

	// corresponding resource
	// the hard limit acts as a ceiling for the soft limit
	// an unprivileged process may only set its soft limit to a
	// value in the range from 0 up to the hard limit
	err = setLimit(targetLimit, targetLimit)
	switch err {
	case nil:
		newLimit = targetLimit
	case syscall.EPERM:
		// lower limit if necessary.
		if targetLimit > hard {
			targetLimit = hard
		}

		// the process does not have permission so we should only
		// set the soft value
		err = setLimit(targetLimit, hard)
		if err != nil {
			err = fmt.Errorf("error setting ulimit without hard limit: %w", err)
			break
		}
		newLimit = targetLimit

		// Warn on lowered limit.

		if newLimit < userLimit {
			err = fmt.Errorf(
				"failed to raise ulimit to IPFS_FD_MAX (%d): set to %d",
				userLimit,
				newLimit,
			)
			break
		}

		if userLimit == 0 && newLimit < minFds {
			err = fmt.Errorf(
				"failed to raise ulimit to minimum %d: set to %d",

View on GitHub (pinned to 329838acdf)

Solutions

  1. Check the wrapped cause with errors.Is(err, syscall.EPERM) and lower IPFS_FD_MAX to at or below the hard limit (see `ulimit -Hn`).
  2. Raise the daemon user's hard nofile limit via /etc/security/limits.conf or systemd LimitNOFILE=, then start the daemon under that environment.
  3. In containers, configure the runtime's nofile ulimits (docker run --ulimit nofile=..., or Kubernetes securityContext) to permit the desired value.

Example fix

// before
os.Setenv("IPFS_FD_MAX", "1000000") // above hard limit
// after
// shell: ulimit -Hn  ->  e.g. 1048576
os.Setenv("IPFS_FD_MAX", "1048576") // at or below the hard limit
Defensive patterns

Strategy: fallback

Validate before calling

var r unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &r); err != nil { return err }
want := uint64(8192)
if v := os.Getenv("IPFS_FD_MAX"); v != "" { want, _ = strconv.ParseUint(v, 10, 64) }
if want > r.Max {
    log.Warnf("IPFS_FD_MAX (%d) exceeds hard limit (%d); clamping", want, r.Max)
}

Type guard

func saneRLimit(cur, max int64) bool { return cur >= 0 && max >= 0 && cur <= max }

Try / catch

changed, newLimit, err := util.ManageFdLimit()
if err != nil {
    var errno syscall.Errno
    if errors.As(err, &errno) && errors.Is(errno, syscall.EPERM) {
        log.Warnf("ulimit raise denied (EPERM), continuing with %d fds", newLimit)
    } else {
        return fmt.Errorf("fd limit: %w", err)
    }
}

Prevention

When it happens

Trigger: ManageFdLimit() when the soft limit is below the target (IPFS_FD_MAX or default 8192), the first setLimit(target, target) returns syscall.EPERM, and the second setLimit(targetLimit, hard) also returns an error (e.g. EPERM again because the soft limit exceeds the hard limit, or EINVAL).

Common situations: Running the daemon as an unprivileged user whose hard limit is lower than the requested IPFS_FD_MAX; container environments (Docker/Kubernetes) that lock rlimits via ulimits settings; misconfigured IPFS_FD_MAX set above the shell's hard limit (ulimit -Hn).

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/33597444a5c7bc56. Report an issue: GitHub.