Fixing Python Paramiko SFTP Uploads That Silently Fail on Large Files
Paramiko is one of the most popular Python libraries for working with:
- SSH
- SFTP
- Remote command execution
- Secure file transfers
- Server automation
Uploading a file is usually straightforward.
Example:
import paramiko
transport = paramiko.Transport(("example.com", 22))
transport.connect(username="user", password="password")
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put("backup.zip", "/remote/backup.zip")
For small files, everything works perfectly.
Problems often begin when uploads become larger.
Developers report situations like:
- Upload reaches 90% and stops
- Upload appears successful but the file is incomplete
- No exception is raised
- Remote file is corrupted
- Connection closes unexpectedly
- Automation continues despite a failed upload
These failures are particularly dangerous because they may appear successful until someone attempts to open the uploaded file.
Imagine an overnight backup process.
Create Backup
β
βΌ
Upload File
β
βΌ
No Error Reported
β
βΌ
Delete Local Backup
The next morning, you discover the remote backup is incomplete and the original has already been removed.
This article explains why large Paramiko SFTP uploads sometimes fail silently and how to build reliable production-ready transfer pipelines.
What You Will Learn From This Article
After reading this guide, you'll understand:
- Why large uploads fail.
- Common Paramiko pitfalls.
- SSH timeout behavior.
- Network reliability issues.
- File integrity verification.
- Retry strategies.
- Production best practices.
How Paramiko SFTP Uploads Work
A simplified workflow looks like this:
Local File
β
βΌ
Read File
β
βΌ
SSH Channel
β
βΌ
SFTP Protocol
β
βΌ
Remote Storage
Each stage can introduce failure conditions.
Why Small Files Usually Work
Small uploads often finish before:
- Network interruptions
- Idle timeouts
- Firewall limits
- SSH keepalive expiration
- Temporary packet loss
Large uploads remain active much longer, increasing the chance of interruption.
Common Symptom #1
Connection Timeout
Example:
Start Upload
β
βΌ
Large File
β
βΌ
Network Delay
β
βΌ
SSH Timeout
Some servers silently terminate inactive or long-running sessions.
Solution
Configure SSH keepalive messages.
Example:
transport.set_keepalive(30)
This periodically sends packets that help keep the SSH session active during lengthy transfers.
Common Symptom #2
Network Interruptions
Large uploads expose more opportunities for:
- Temporary packet loss
- VPN reconnects
- Wi-Fi instability
- Firewall resets
A small interruption may terminate the transfer.
Solution
Whenever possible:
- Use wired connections
- Upload from stable servers
- Minimize VPN interruptions
Reliable networking improves successful transfers.
Common Symptom #3
Assuming put() Guarantees Success
Many developers write:
sftp.put(
local_file,
remote_file
)
print("Done")
The message appears.
The remote file exists.
Everything seems successful.
But:
Remote File
β
Complete File
Always verify the result.
Verify Remote File Size
Example:
local_size = os.path.getsize(local_file)
remote_size = sftp.stat(
remote_file
).st_size
Compare:
Local Size
=
Remote Size
If sizes differ, the upload should be treated as failed.
Common Symptom #4
Corrupted Files
Sometimes:
Upload Completes
yet:
Archive Won't Open
or:
Checksum Doesn't Match
This indicates corruption.
Verify Checksums
Generate hashes locally.
Example:
hashlib.sha256()
If possible, compare with a checksum calculated on the remote server.
Matching hashes provide much stronger assurance than matching file sizes alone.
Common Symptom #5
Disk Space Issues
The upload succeeds until:
Remote Disk
β
Full
Some servers return generic SFTP errors.
Others terminate the connection unexpectedly.
Always verify available storage before transferring large files.
Common Symptom #6
Permission Problems
Uploads may silently fail if:
- Directory permissions are incorrect.
- File ownership is restricted.
- Quotas are exceeded.
Confirm the target directory is writable before starting a lengthy transfer.
Use Progress Callbacks
Paramiko supports progress monitoring.
Example:
def progress(sent, total):
print(f"{sent}/{total}")
sftp.put(
local_file,
remote_file,
callback=progress
)
Benefits include:
- Progress visibility
- Easier debugging
- Transfer monitoring
- Detecting stalled uploads
Add Retry Logic
Temporary network failures happen.
Instead of immediately aborting:
Upload
β
Failure
β
Retry
Retrying after a short delay often resolves transient issues.
Use exponential backoff to avoid overwhelming the server.
Don't Delete the Source File Immediately
Avoid this pattern:
Upload
β
Delete Local File
Instead:
Upload
β
Verify Size
β
Verify Integrity
β
Delete Local Copy
This greatly reduces the risk of data loss.
Handle Exceptions Explicitly
Example:
try:
sftp.put(...)
except Exception as error:
logger.exception(error)
Never suppress exceptions with empty except blocks.
Proper logging makes production troubleshooting much easier.
Monitor Transfer Duration
Long transfers may indicate:
- Network congestion
- Slow storage
- Server overload
Recording transfer time helps identify infrastructure problems before they become failures.
Large Files May Require More Time
Some automation systems enforce execution limits.
Example:
Job Timeout
=
10 Minutes
Your upload requires:
15 Minutes
The process is terminated before completion.
Ensure application-level timeouts exceed expected upload durations.
Atomic Upload Strategy
Instead of uploading directly to the final filename:
backup.zip
upload to:
backup.zip.tmp
After successful verification:
Rename
backup.zip.tmp
β
backup.zip
This prevents other systems from reading incomplete files.
Real-World Example
A nightly backup system uploads:
Database Backup
β
2.5 GB File
β
SFTP Upload
The automation reports success.
However, the remote file is only:
1.9 GB
The script deletes the local backup immediately.
Recovery becomes impossible.
The solution:
- Enable keepalive
- Verify file size
- Compare checksums
- Rename atomically
- Delete the local copy only after verification
The backup process becomes reliable.
Production Checklist
Before deploying Paramiko uploads:
β Enable SSH keepalive
β Verify remote file size
β Compare checksums
β Add retry logic
β Log transfer progress
β Monitor upload duration
β Handle exceptions properly
β Confirm disk space
β Upload to temporary filenames
β Delete local files only after validation
Common Mistakes to Avoid
Avoid:
β Assuming put() alone guarantees integrity
β Ignoring network instability
β Deleting source files immediately
β Suppressing exceptions
β Skipping checksum verification
β Forgetting SSH keepalive
β Ignoring disk quotas
β Uploading directly to production filenames
Performance Considerations
For very large files:
- Compress data when appropriate.
- Avoid unnecessary encryption layers on already encrypted files.
- Use stable network connections.
- Monitor server resource utilization.
- Schedule transfers during off-peak hours.
These optimizations improve both reliability and throughput.
Why This Bug Is Difficult to Detect
Unlike obvious failures that raise exceptions, incomplete SFTP uploads often leave behind files that appear legitimate at first glance.
The filename is correct.
The timestamp looks normal.
The upload process completed.
Only later does someone discover:
- The archive cannot be extracted.
- The media file is corrupted.
- The backup cannot be restored.
Without integrity verification, these silent failures can remain hidden for days or even weeks.
Wrapping Summary
Paramiko provides a powerful and flexible way to automate secure file transfers, but large SFTP uploads introduce challenges that smaller files rarely expose. Network interruptions, SSH session timeouts, storage limitations, permission issues, and incomplete transfers can all produce files that appear to upload successfully while actually being truncated or corrupted.
A production-ready upload workflow should go beyond simply calling sftp.put(). By enabling SSH keepalive messages, monitoring transfer progress, verifying remote file sizes and checksums, implementing retry logic, uploading to temporary filenames, and only deleting local files after successful validation, developers can dramatically improve the reliability of automated file transfers.
Treat every large upload as a critical operation that requires verification. A few additional validation steps can prevent silent data corruption and ensure your backups, reports, and deployment artifacts arrive exactly as intended.
π€ Share this article
Sign in to saveRelated Articles
Comments (0)
No comments yet. Be the first!