What you see
$ sftp user@server
subsystem request failed on channel 0
Connection closed
scp uses the same service since OpenSSH 9.0, so it fails too:
subsystem request failed on channel 0
scp: Connection closed
Plain ssh user@server still works, because only the SFTP part is missing.
Check the server
sudo sshd -T | grep -i '^subsystem'
No output means no subsystem is defined, which is the OpenSSH default when the line is missing. It often happens after someone replaces sshd_config with a short hardened version, or the line was commented out. sshd -t does not warn you about this.
The fix
Add one of these to /etc/ssh/sshd_config, outside any Match block. The first runs SFTP inside sshd and needs no separate program:
Subsystem sftp internal-sftp
Or the classic form, with the path for your system:
Subsystem sftp /usr/lib/openssh/sftp-server
Common paths:
| System | Path to sftp-server |
|---|---|
| Debian, Ubuntu | /usr/lib/openssh/sftp-server |
| RHEL, Fedora, Rocky, Alma | /usr/libexec/openssh/sftp-server |
| Alpine | /usr/lib/ssh/sftp-server, from the package openssh-sftp-server |
Then validate and reload. The service is ssh on Debian and Ubuntu and sshd on Red Hat style systems:
sudo sshd -t && sudo systemctl reload ssh
Keep your current session open until a new login works.
With the line back, sftp works as usual. For daily use, see sftp commands with examples.
On a NAS or a router
Appliances turn SFTP on in their own settings, not in sshd_config. On a Synology NAS, enable the SFTP service in Control Panel, File Services, FTP. On OpenWrt, SFTP needs the openssh-sftp-server package.
A workaround when you cannot change the server
For file copies, tell scp to use the old protocol, which needs no subsystem:
scp -O file.txt user@server:/tmp/
You can also pipe over plain SSH, since the login itself works:
tar -cf - folder | ssh user@server 'tar -xf - -C /tmp'
Similar messages, different causes
The path is wrong
When the line exists but the program is not there, the subsystem request succeeds and the program then fails to start. You do not get the subsystem message, only this:
Connection closed.
Connection closed
sshd -t does not check the path, so test the file on the server:
sudo sshd -T | grep -i '^subsystem'
ls -l /usr/lib/openssh/sftp-server
Correct the path, install the missing package, or switch to internal-sftp.
The shell prints something
Received message too long 1466264675
Ensure the remote shell produces no output for non-interactive sessions.
SFTP reads the first bytes of output as a binary length, so any text from the shell breaks it. In this message, those large numbers are the letters of the text being read as a number. Check for output:
ssh user@server /bin/true | wc -c
Anything other than 0 means a startup file such as ~/.bashrc is printing. Put this at the top of that file so that the rest only runs in interactive shells:
case $- in
*i*) ;;
*) return ;;
esac
The account has a nologin shell, or a forced command
The same Received message too long error appears here, because nologin or a ForceCommand prints text. For a nologin user, internal-sftp worked in our test, since it does not start the user's shell. Under a ForceCommand, change the setting so that it does not apply to SFTP users, or set it to internal-sftp for them.
Questions
What does subsystem request failed on channel 0 mean?
The login worked, but the server has no SFTP service configured. Add Subsystem sftp internal-sftp to sshd_config and reload SSH.
Why does ssh work but sftp does not?
ssh only needs a shell, while sftp also asks the server to start its SFTP subsystem. If the Subsystem line is missing or points to a wrong path, only file transfers fail.
Does scp need the SFTP subsystem?
Since OpenSSH 9.0, yes, so it fails the same way. scp -O uses the old protocol, which works without it.