An scp command that worked in a script for years can fail on a current client with a path error that has nothing to do with the tunnel. The VPN carried the bytes; the client asked the server for a name the server could not resolve. Current OpenSSH scp transfers through SFTP by default, and SFTP does not do shell-style expansion the way the legacy protocol did. Walking the command outward from your own account shows where the path is really being interpreted.

Start from the account, then the directory it can write

The colon splits two namespaces, and only the left side belongs to the machine you are typing on. Everything after it is resolved by the server, under the account you authenticated as, inside whatever filesystem view that account has. Confirm both before you compose the command, because a path that is correct for the administrator is not automatically correct for the transfer user. That difference is the source of most permission errors that look like network faults.

Ask the server for its own view: ssh [email protected] pwd and ssh [email protected] ls -ld /srv/archive. If the second command reports permission denied, the tunnel is fine and the path is unusable for that account. Fix ownership or pick a different destination rather than widening permissions so the transfer can proceed.

A restricted SFTP configuration can present a chroot as the root of the filesystem. Inside that view an absolute path is absolute within the chroot, which is not the same location the administrator sees on the host.

Name both sides of the colon explicitly

An upload should state the remote file name instead of assuming the local basename will be acceptable on the far side.

scp q3-invoice.csv [email protected]:/home/transfer/drop/q3-invoice.csv

A download should state the local destination for exactly the same reason. The two namespaces are independent, and a script that assumes they match breaks the first time the remote tree uses a different layout.

scp [email protected]:/srv/archive/2026-q3.csv ./2026-q3.csv

Avoid ~otheruser in a maintained script. Expanding another account home directory was a remote-shell feature, and an SFTP server may not implement the extension that emulates it. Write the absolute path the account can actually open, and quote local paths containing spaces rather than copying quote layers that were written for a shell on the server.

Know which protocol your scp actually uses

Since OpenSSH 9.0 the client uses SFTP by default, and distributions adopt or backport that behaviour on their own schedule. The version string tells you what the client intends, but a vendor build can differ from upstream, so check the client you actually run: ssh -V.

The two protocols resolve names differently. Legacy SCP asks the remote user shell to expand the path, so wildcards and tildes are handled by that shell with its own rules. SFTP issues file-transfer operations instead, so a wildcard is either expanded by the client or not expanded at all. Both travel inside SSH to the same machine, which is why one host can behave differently under two clients.

scp -v prints the subsystem it requests, and an sftp subsystem line confirms the modern path is in use. scp -O forces the legacy protocol where it is supported and genuinely required, and it brings its own quoting rules back with it. It is not a VPN option, not a way to enable anything on the server, and not a reason to relax host-key checking.

Test the path before the script depends on it

A path problem surfaces at the worst possible time, in an automated job at night with nobody watching. Prove the destination first with a small file and the exact account the job uses, and keep that test command beside the job definition. If the test needs a different account or a different directory, the job will need one too.

Check the server side as well. grep -i subsystem /etc/ssh/sshd_config shows whether an SFTP subsystem is configured, and sftp -b /dev/null [email protected] exits successfully only when that subsystem answers. A host that accepts SSH logins but has no subsystem fails every modern transfer while looking perfectly healthy in a login test.

Record the client version, the protocol in use and the absolute remote path in the job notes. When the next upgrade changes a default, that note is the difference between a five-minute fix and an afternoon of guessing.

פֿאַרבונדענע אַרטיקלען