CompleteFTP: System.OutOfMemoryException during SFTP, or a service that stops responding

Sessions are dying with System.OutOfMemoryException in the diagnostics log, or the whole server has gone quiet: transfers crawl, new logins time out, CompleteFTP Manager will not connect, and a service restart brings everything back for a day or a week. Those two things arrive in the same sentence from users but they are separate failures, they leave different evidence, and the second one frequently has no out-of-memory error in it at all.

Three names are used throughout, because the words "client" and "server" point in opposite directions depending on which one you mean:

  • your CompleteFTP server is the CompleteFTP service on the machine you administer.
  • the connecting client is whatever connects to it over SFTP: WinSCP, FileZilla, OpenSSH sftp, a partner's scheduler, your own application.
  • the upstream server is the FTP/SFTP server behind your CompleteFTP server when it is running as a multiprotocol gateway.

If System.OutOfMemoryException is being thrown inside your own application while it talks to a remote server, the memory being exhausted is your application's, not CompleteFTP's, and nothing below applies to it.

Which situation are you in?

Answer from what people are telling you right now.

Which parts are shared. The short version and Where the limits are below apply to both cases, and so do most of the entries in When it doesn't work, which are tagged with the cases they belong to. The two case sections are the branch: read the one you land on and skip the other.

Case What is happening to new SFTP logins What CompleteFTP Manager does Read
A New logins still succeed. Individual sessions fail, some transfers break part way, some users are unaffected Connects normally Case A
B New logins hang and time out, or are refused. Existing sessions stall Cannot connect, or connects and then times out Case B

Telling them apart from the log alone

Both cases can put System.OutOfMemoryException in Diagnostics.log, so the exception text does not separate them. The session number does.

Every log line carries a tag of the form [Session.{n}:{site name}.{port}:{user name}:{remote IP}]. That {n} is a counter that starts at 1 when the service starts and increases by one for every accepted connection, logged in or not.

Confirm the service has not restarted under you before you read anything into the counter. The counter resets to 1 on every start, so a restart makes a stalled server look like a busy one. The Linux unit is configured to restart itself automatically after a crash, which makes this the normal case there rather than the exception: check uptime with systemctl status completeftp (the Active: line) and cross-check against the INFO Server ... Starting server lines in Diagnostics.log, which are written once per start on both platforms. On Windows nothing restarts the service unless recovery actions were configured, so one Starting server line usually means one run.

With uptime established:

  • Session numbers keep climbing after the incident started. Your CompleteFTP server is still accepting connections. That is Case A.
  • Session numbers stop advancing, and what remains in the log is repeats from the same handful of sessions, or nothing at all. Nothing new is getting in. That is Case B.

One line decides it on its own. This one is thrown while accepting a brand-new connection, and it means memory ran out before the connection existed:

2026-08-03 09:14:22,118 ERROR SocketListener [Session.481233:Default Site.22:user?:10.4.11.60] OnConnected failed: Exception of type 'System.OutOfMemoryException' was thrown.

If that line is present, treat it as Case B regardless of what else is in the log.

The session counter is also a rate meter. Divide the highest session number by the time since the service last started. Half a million sessions in three days is roughly two connections per second, sustained, which is a load question rather than a memory question.

The short version

  1. Record the memory figure before you restart anything. A restart erases the only measurement that distinguishes "the process grew" from "the machine was full".
    • Windows: Task Manager → Details → CompleteFTPService.exe, the Working set (memory) column.
    • Linux: the server runs as dotnet /usr/lib/completeftp/bin/completeftp.dll. Get its process ID with systemctl show completeftp -p MainPID and read its resident set with ps -o rss= -p <pid> (kilobytes). Resident set is the figure that corresponds to the Windows working set. The Memory: line in systemctl status is the whole control group and reads higher, so do not mix the two.
  2. Note the highest Session. number in Diagnostics.log and the time the service last started. That gives you the case above and your connection rate.
  3. Turn the logging level up to Debug and leave it there until it happens again. Your CompleteFTP server reports its own memory usage only at Debug, and raising the level is not retroactive: a log captured at the default Information level will contain no memory lines, which is not evidence that memory was fine. The procedure is in How to enable debug logging in CompleteFTP.
  4. Then:

Where the limits are, and what units they use

Nothing in this table is set to a protective value out of the box. Max. non-HTTP connections to site ships as 0, which means unlimited, and Max. connections per user is unset, which also means unlimited. Both cases below refer back to this table.

CompleteFTP Manager is a Windows application. Administering a Linux server means either running the manager on a Windows machine and pointing it at the server's admin port, or using the completeftp command line on the server itself, which is enabled by default on Linux.

The manager shows timeouts in seconds and disk quotas in MB. The CLI and JSS properties are the stored values, which are milliseconds and bytes. Setting timeoutIdle=300 from the command line asks for 300 milliseconds, not five minutes.

What it does CompleteFTP Manager CLI property CLI unit Shipped default
Caps total SFTP/FTP/FTPS connections to a site Site → Limits and TimeoutsMax. non-HTTP connections to site maxConnections count 0 (unlimited)
Caps connections held by one account Site → Limits and TimeoutsMax. connections per user maxConnectionsPerUser count unset (unlimited)
Closes a connection that has not logged in Site → Limits and TimeoutsTimeout for logging in (seconds) timeoutLogin ms 60,000 (60 s)
Closes a logged-in session that sends nothing Site → Limits and TimeoutsTimeout for idle sessions (seconds) timeoutIdle ms 300,000 (5 min)
Socket read/write timeout during transfers Site → Limits and TimeoutsTimeout for stalled transfers (seconds) timeoutStalled ms 60,000 (60 s)
Login attempts allowed per session Site → Limits and TimeoutsMax. allow login attempts maxLoginAttempts count 3
Failed logins before an IP is banned Site → IP Filtering and Auto-BanningAuto-BanningNumber of failures allowed in period autoBanTriggerCount count 10
Window those failures must fall in Site → IP Filtering and Auto-BanningAuto-BanningFailure counting period (seconds) autoBanTriggerPeriod ms 300,000 (5 min)
How long the ban lasts Site → IP Filtering and Auto-BanningAuto-BanningDuration of ban (seconds) autoBanDuration ms 3,600,000 (1 hour)
Per-user disk quota (drives size watchers) User → Quotas and LimitsDisk usage (MB) quotaStorage bytes unset
Per-user transfer rate cap User → Quotas and LimitsDownload (kB/s), Upload (kB/s) quotaSpeedDownload, quotaSpeedUpload bytes/s unset

Setting 0 in the manager's timeout fields displays as No timeout and means infinite, not immediate. Entering a negative number in Disk usage (MB) clears the quota rather than setting one.

Changes reach the running server when you click APPLY CHANGES in the manager. From the command line the equivalent is one invocation per property, which applies itself:

completeftp site set "Default Site" maxConnections=400
completeftp site set "Default Site" maxConnectionsPerUser=20
completeftp site set "Default Site" timeoutLogin=30000

Neither route requires a service restart.

Case A. Sessions fail with an out-of-memory exception while logins keep succeeding

Your CompleteFTP server is up, admissions are working, and a subset of sessions is being killed. The allocation that failed belongs to one session's work, so the question is which work.

1. Get the exception, not just the first line. The message and the exception are logged as separate lines. Errors.log and the manager's real-time view show you the message; the exception type and its stack are in Diagnostics.log immediately after it. Take that file, not a screenshot of the error list.

2. Establish whether the process is actually large. With Debug logging on, your CompleteFTP server logs its own working set on every login and every logout:

2026-08-03 09:15:02,441 DEBUG MemoryUsage [Session.481240:Default Site.22:jdoe:10.4.11.60] Working set = 128.44 MB

Read a day of those. A process that sits in the low hundreds of MB and then throws System.OutOfMemoryException did not fill itself; something else on the machine took the memory, or a single allocation was very large. A process whose working set climbs steadily across the day and never falls back after logouts is the opposite problem, and belongs in Case B.

3. Find which operation throws. Match the timestamp to the SFTP request in the same session. The three that recur:

  • A file read that fails: ERROR FileDetails [...] /path/to/file: read file failed, with the exception on the next line. Note the file size.
  • A packet-processing failure: ERROR SFTPConnection [...] Exception thrown in packet processing: followed by the exception. See Reading the output for what the connecting client is told when this happens.
  • A receive failure: ERROR SFTPConnection [...] Receive error: Exception of type 'System.OutOfMemoryException' was thrown.

4. Check what else the machine is doing at that moment. Anti-virus scanning the transfer directory, a backup agent, another service on the same box. Storage and file-system work performed inside your CompleteFTP server's process counts against its address space even when the file itself is on a network share.

5. If it is one user or one folder, cap that user rather than the site. Max. connections per user bounds the number of concurrent sessions a single account can hold, which bounds the number of concurrent transfers it can run. It is the smallest change that stops one client starving the rest, and it does not affect anyone else.

Case B. The service is running but nothing is getting through

New logins hang or are refused, the manager cannot connect, and stopping and starting the service fixes it for a while. Recovery and diagnosis are separate jobs, in that order.

1. Recover. Take the memory figure and the highest session number first, then restart: Services → Complete FTP Server → Restart, or sc stop CompleteFTP then sc start CompleteFTP, on Windows; systemctl restart completeftp on Linux.

While you are in the Windows Services console, check Recovery on Complete FTP Server and set Restart the Service if it says Take No Action. An upgrade does not add recovery actions to a service that already exists, so a server upgraded from an old installation often has none. The Linux unit already restarts itself after a crash.

If the service will not stop, do not assume it is stuck inside CompleteFTP. Raising the logging level to Debug before issuing the stop makes the log show how far shutdown got, but if CompleteFTP Manager cannot connect there is no way to raise it at that moment. This is the argument for leaving Debug on between incidents rather than trying to switch it on during one.

2. Decide whether it filled up or seized up. These need different fixes:

  • Filled up. The Working set lines climb across the run and do not come back down, or the machine's own memory is exhausted at the moment of failure. The accept-time OnConnected failed line above is the strongest single indicator.
  • Seized up. Memory is unremarkable. What is exhausted is connections, threads or CPU. Look for a very high session number relative to uptime, hundreds of established connections, or the CompleteFTP process pinned near 100% CPU. Read the CPU figure from the same process you measured in step 1: the CPU column in Task Manager on Windows, top -p <pid> on Linux.

3. Count sessions, at the next occurrence. This measurement only exists while the server is still in the bad state, so it is what you do before restarting if anything can still reach the server, and otherwise what you prepare for next time.

Monitoring → Connections in CompleteFTP Manager lists Site, Username, Protocol, Remote Address, Local Port, Connected and Logged In per live connection, with Kill selected connection(s) and Kill all connections. Sessions that show a Connected time but no Logged In time, in quantity, are connections that never authenticated.

The manager is often the thing that cannot connect in this case, so on Linux use completeftp monitor connection list --site "Default Site" and completeftp monitor connection kill <sessionID> instead. On Windows the same commands exist but the admin CLI is off by default: enabling it changes the service binary path and needs a service restart, so it is preparation to do now, not a step you can take mid-incident. The guide page the Windows admin CLI has the procedure.

4. Set the two limits that bound the damage. Both are on the site, both take effect without a restart:

  • Max. non-HTTP connections to site. Once the site is over this number, a further SFTP connection is refused at the point it asks to authenticate. Your CompleteFTP server logs WARN SFTPConnection [...] Maximum site connections exceeded - 400 allowed and the connecting client is disconnected with the text Too many connections to this site. Pick a number your machine has been observed to carry, not an aspirational one: refusing the 401st connection is a far better outcome than becoming unreachable to all 400.
  • Max. connections per user, so that one runaway scheduler cannot consume the site limit by itself.

5. If it seized up, look at what blocks per session, in this order: disk-usage quotas, per-user speed limits, and any file-system extension or gateway hop. All three are covered as failure modes below.

When it doesn't work

Ordered by how often each turns up in support tickets. The case tags say which situation the item belongs to.

1. The machine really was out of memory, and CompleteFTP was the biggest process rather than the guilty one. (A, B) The CompleteFTP service is a 64-bit process, so it has no 2 GB address ceiling of its own: when it cannot allocate, the machine could not allocate. Check the page file, the other services on the box, and whether the VM has been resized. A working set of a few hundred MB under load is normal; a working set that is a large fraction of physical RAM is the finding.

2. Connections accumulate because nothing is bounding them. (B) With both connection limits at their shipped unlimited values, the number of simultaneous sessions is bounded only by the machine. A client that reconnects several times a second, or a partner whose retry loop has no backoff, will reach that boundary. The session counter and the Connections tab both quantify it, and the fix is step 4 of Case B.

3. Connections that never log in. (A, B) Auto-banning counts failed authentication attempts only. An address that opens connections and never offers a credential is never banned, no matter how many it opens, so an unauthenticated flood does not appear in the auto-ban list. What bounds it is Timeout for logging in, which closes such a connection after 60 seconds by default, and Max. non-HTTP connections to site, which counts every open connection including unauthenticated ones. Lower the login timeout before you touch the auto-ban settings. For blocking a specific source outright, see Restricting access to CompleteFTP by IP address.

4. A disk-usage quota over a large or busy folder. (B, and A on a heavily loaded server) Giving a user a quota under Quotas and Limits → Disk usage (MB) makes your CompleteFTP server attach a size watcher to each folder that user owns while a session is open. On Windows that is a file-system watcher plus a recursive size calculation, recomputed a few seconds after every change inside the tree. Over a directory with a very large number of files, or one being written to continuously, this is significant sustained work per session. Remove the quota from the affected users and see whether responsiveness returns before investigating anything else. Users with no quota set attach no watchers at all.

5. Per-user speed limits under load. (B) Download (kB/s) and Upload (kB/s) are enforced by making the transfer wait, and the wait occupies the thread handling that session. A few limited users cost nothing noticeable; many simultaneously limited users mean many simultaneously waiting threads. If a hang correlates with peak concurrency and speed limits are widely applied, remove them from a subset and re-test.

6. Your CompleteFTP server is a gateway. (A, B) In gateway configurations the log tag carries a Gateway.{n} suffix, and the connection those lines describe is your CompleteFTP server acting as a client of the upstream server. Memory and connection pressure there is driven by the upstream protocol: over FTP a separate data connection is opened for every directory listing and every file transfer, by design, so a workload of many small files produces many short-lived upstream connections and ports. Count them on the upstream server before concluding the gateway is leaking.

7. Debug logging left on permanently. (A, B) Debug is what you need to diagnose this, and it writes a great deal more to disk. Turn it back down once you have the log you came for. See How to enable debug logging in CompleteFTP for the production trade-offs and rollover settings.

8. send failed: socket closed everywhere, and no memory error. (A) This is logged when your CompleteFTP server tries to write to a connection the connecting client has already dropped without completing the SSH close sequence. Some clients do this routinely at the end of every transfer. On its own it is noise, not a fault, and it is not evidence of a memory problem. The same is true of Connection abruptly closed: An established connection was aborted by the software in your host machine.

9. The log is silent across the whole incident. (B) No errors, no new session numbers, nothing. Then the connections are not reaching your CompleteFTP server: look at the firewall, the load balancer, and whether another process has taken the port. ERROR Server Unhandled exception in server is the only line that indicates a failure inside your CompleteFTP server that nothing caught, and its absence is informative.

10. Transfers stall and the log shows a window-space timeout instead. (A) That is a different failure with a different remedy; see ConsumeWindowSpace timed out in CompleteFTP and edtFTP.

Reading the output

Where the files are. On Windows, C:\ProgramData\Enterprise Distributed Technologies\Complete FTP\Logs. On Linux, /var/log/completeftp. Diagnostics.log carries everything at the configured level; Errors.log carries warnings and above and is much smaller, which makes it the faster place to confirm that an incident happened and the wrong place to diagnose it, because it does not contain the surrounding session activity.

How an exception is written. The message and the exception occupy consecutive lines, and only the first carries the timestamp, level, logger and session tag:

2026-08-03 09:14:19,882 ERROR SFTPConnection [Session.481197:Default Site.22:jdoe:10.4.11.60] Exception thrown in packet processing: server error: check server log at 2026-08-03 09:14:19,882
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at ...

Searching for the exception type alone finds the second line and loses the session tag, the timestamp and the operation. Search for the message, then read down.

What the connecting client sees. When packet processing throws, your CompleteFTP server disconnects that session with SSH disconnect reason 2 (protocol error) and the text server error: check server log at <timestamp>. The user reports a protocol error or a corrupt-MAC error from their client, which reads as a client-side or network fault and is neither: the timestamp in that message is the one to look up in Diagnostics.log. Clients that report Corrupt Mac on input or an incorrect MAC at the same moment as an out-of-memory exception on your CompleteFTP server are seeing the truncated response, not a cipher problem.

What your CompleteFTP server reports about its own memory. Two Debug-level lines, and no others:

DEBUG MemoryUsage [Session.481240:Default Site.22:jdoe:10.4.11.60] Working set = 128.44 MB
DEBUG SSHServerChannel [Session.481240:Default Site.22:jdoe:10.4.11.60] Channel 0: Total memory use = 134217728 bytes

The first is the whole process's working set, emitted on each login and logout. It is the same quantity as Task Manager's working set on Windows and as resident set size on Linux, so it lines up with the figure recorded in step 1 by either route. The second is the managed heap, emitted every 500 SFTP data messages on a channel, so it only appears during active transfers.

There is no memory alarm to switch on. The Monitoring panel's Performance tab plots connections, logins, failed logins, filter and auto-ban blocks, files and bytes transferred. Memory is not among them, and email notifications are driven by file events rather than by server health. To be warned before the machine fills, point whatever monitoring already covers the host at the working set of CompleteFTPService.exe on Windows, or at the resident set of the completeftp.dll process on Linux.

If you are on an older release

Upgrade. These were fixed and the fix is only in the release named.

Symptom Affected Fixed in
Memory leak in the file server 11.0.3, 11.0.4 11.0.5
High memory use downloading large files over SFTP up to 12.0.x 12.1.0
Memory leak when a custom command is called from a process trigger up to 12.1.4 12.1.5
General SFTP memory management 13.0.0 13.0.1
TLS session memory leak up to 23.0.3 23.0.4
FTPS memory management up to 25.0.4 25.0.5
32-bit service process, capped near 2 GB whatever the machine had before 22.0.0 22.0.0

Related