You run from_pretrained() to download a model and the process dies halfway through with a cryptic OS-level error. The download was going fine, then suddenly:
Traceback (most recent call last):
File "load_model.py", line 4, in <module>
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
File "/usr/local/lib/python3.11/site-packages/transformers/modeling_utils.py", line 3456, in from_pretrained
resolved_archive_file = cached_file(
File "/usr/local/lib/python3.11/site-packages/transformers/utils/hub.py", line 406, in cached_file
http_get(
File "/usr/local/lib/python3.11/site-packages/huggingface_hub/file_download.py", line 1042, in http_get
shutil.copyfileobj(response.raw, temp_file)
File "/usr/local/lib/python3.11/shutil.py", line 202, in copyfileobj
buf = fsrc.read(length)
File "/usr/local/lib/python3.11/site-packages/urllib3/response.py", line 879, in read
data = self._raw_read(amt)
OSError: [Errno 28] No space left on device
This error has nothing to do with your GPU or model architecture. The disk partition that holds ~/.cache/huggingface/ is full. This guide explains exactly why it happens and gives five concrete fixes in order of effort.
Every time you call AutoModel.from_pretrained(), AutoTokenizer.from_pretrained(), or any HuggingFace download function, the library stores the downloaded weights, tokenizer files, and configuration on disk so that subsequent loads are instant — no re-download needed.
By default, that cache lives at:
~/.cache/huggingface/hub/
On most Linux systems — including cloud VMs (AWS EC2, Google Cloud, DigitalOcean) and WSL2 on Windows — the home partition (/home or /) is deliberately kept small: 20–50 GB is common. A single model like Mistral-7B weighs about 14 GB. LLaMA-2-13B is 26 GB. If you download two or three models during experimentation, you can fill a home partition entirely without noticing.
The download is written to a temporary file first (.incomplete suffix inside the cache blob directory) and then copied to its final location via shutil.copyfileobj. That is the line in the traceback: the copy step itself fails because no more bytes can be written to the partition.
Check your current usage right now:
# Overall partition usage
df -h ~
# How much space the HuggingFace cache is consuming
du -sh ~/.cache/huggingface/
# Break it down per model
du -sh ~/.cache/huggingface/hub/*/
Example output on a typical cloud VM after a few model downloads:
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 49G 47G 786M 99% /
8.3G /home/ubuntu/.cache/huggingface/hub/models--bert-base-uncased/
14G /home/ubuntu/.cache/huggingface/hub/models--mistralai--Mistral-7B-v0.1/
26G /home/ubuntu/.cache/huggingface/hub/models--meta-llama--Llama-2-13b-hf/
The fix is straightforward: either redirect the cache to a larger partition, remove models you no longer need, or both. All five approaches below work without changing your training or inference code in any fundamental way.
This is the cleanest permanent fix. The HF_HOME environment variable tells the entire HuggingFace ecosystem — transformers, diffusers, datasets, huggingface_hub — where to store all cached files. Set it once and every future download lands on the larger partition.
First, identify a partition with enough space. On a cloud VM with a mounted data disk, or a machine with a secondary drive, run df -h to find it:
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 49G 47G 786M 99% /
/dev/sdb1 500G 12G 464G 3% /data
The /data partition has 464 GB free. Create a directory for the cache and export HF_HOME:
# Create the target directory
mkdir -p /data/huggingface_cache
# Export for the current shell session (temporary)
export HF_HOME=/data/huggingface_cache
# Verify it is picked up
python -c "from huggingface_hub import constants; print(constants.HF_HOME)"
# /data/huggingface_cache
To make it permanent, add it to your shell profile so it applies to every new session:
# For bash users
echo 'export HF_HOME=/data/huggingface_cache' >> ~/.bashrc
source ~/.bashrc
# For zsh users
echo 'export HF_HOME=/data/huggingface_cache' >> ~/.zshrc
source ~/.zshrc
Confirm the change took effect before and after:
# Before (old partition)
df -h ~/.cache/huggingface/
# Filesystem Size Used Avail Use% Mounted on
# /dev/sda1 49G 47G 786M 99% /
# After setting HF_HOME and re-running from_pretrained()
df -h /data/huggingface_cache/
# Filesystem Size Used Avail Use% Mounted on
# /dev/sdb1 500G 26G 450G 6% /data
If you have existing cached models you still want to use, move them to the new location rather than re-downloading:
mkdir -p /data/huggingface_cache/hub
mv ~/.cache/huggingface/hub/* /data/huggingface_cache/hub/
Two related environment variables give finer control if you need it:
# HF_DATASETS_CACHE — override cache specifically for `datasets` downloads
export HF_DATASETS_CACHE=/data/huggingface_cache/datasets
# TRANSFORMERS_CACHE — legacy variable, superceded by HF_HOME in transformers >= 4.22
# Still respected as a fallback in some older versions
export TRANSFORMERS_CACHE=/data/huggingface_cache/hub
HF_HOME is the authoritative variable and the one to prefer.
If you cannot move the cache (shared server, no secondary disk, no admin access), deleting models you no longer need is the quickest way to recover space. The huggingface-cli command ships with huggingface_hub and includes an interactive cache manager.
# Ensure huggingface_hub is installed
pip install -U huggingface_hub
# Launch the interactive cache browser
huggingface-cli delete-cache
The tool opens a terminal UI that lists every cached model and dataset with its size on disk. Use arrow keys to navigate, Space to select models for deletion, and Enter to confirm. It will show a summary of how many bytes will be freed before making any changes.
? Select revisions to delete: (Use arrow keys, <space> to select, <a> to toggle all, <i> to invert)
❯ ○ meta-llama/Llama-2-13b-hf main (26.0 GB) last used 14 days ago
○ mistralai/Mistral-7B-v0.1 main (14.1 GB) last used 2 days ago
○ bert-base-uncased main (0.4 GB) last used 5 hours ago
○ openai/clip-vit-large-patch14 main (1.7 GB) last used 3 days ago
If you prefer a non-interactive approach for scripting or automation, scan the cache programmatically and delete by model name:
from huggingface_hub import scan_cache_dir, HFCacheInfo
# Get a full picture of what is cached
cache_info: HFCacheInfo = scan_cache_dir()
print(f"Total size on disk: {cache_info.size_on_disk_str}")
print(f"Number of cached repos: {len(cache_info.repos)}")
print()
# Print each repo with its size
for repo in sorted(cache_info.repos, key=lambda r: r.size_on_disk, reverse=True):
print(f"{repo.repo_id:<55} {repo.size_on_disk_str:>10} (last used: {repo.last_accessed_str})")
Total size on disk: 48.5 G
Number of cached repos: 4
meta-llama/Llama-2-13b-hf 26.0 G (last used: 14 days ago)
mistralai/Mistral-7B-v0.1 14.1 G (last used: 2 days ago)
openai/clip-vit-large-patch14 1.7 G (last used: 3 days ago)
bert-base-uncased 0.4 G (last used: 5 hours ago)
To delete a specific revision programmatically:
from huggingface_hub import scan_cache_dir
cache_info = scan_cache_dir()
# Collect revision hashes for a model you want to remove
revisions_to_delete = []
for repo in cache_info.repos:
if repo.repo_id == "meta-llama/Llama-2-13b-hf":
for revision in repo.revisions:
revisions_to_delete.append(revision.commit_hash)
print(f" Queuing for deletion: {revision.commit_hash[:8]} ({revision.size_on_disk_str})")
# Execute deletion — returns a DeleteCacheStrategy with a summary
strategy = cache_info.delete_revisions(*revisions_to_delete)
print(f"\nFreeing {strategy.expected_freed_size_str}")
strategy.execute()
print("Done.")
The HuggingFace cache uses a content-addressed blob store. Each model directory is safe to delete in its entirety. If you know which models you no longer need, you can remove them directly with standard shell commands — no special tooling required.
The cache directory structure looks like this:
~/.cache/huggingface/hub/
├── models--bert-base-uncased/
│ ├── blobs/
│ │ ├── 8a6d4afc... (config.json content)
│ │ └── fc4b6c59... (model.safetensors content)
│ ├── refs/
│ │ └── main (points to a commit hash)
│ └── snapshots/
│ └── 1dbc166cf701.../ (symlinks into blobs/)
│ ├── config.json -> ../../blobs/8a6d4afc...
│ └── model.safetensors -> ../../blobs/fc4b6c59...
├── models--mistralai--Mistral-7B-v0.1/
└── models--meta-llama--Llama-2-13b-hf/
Inspect sizes, then delete the folders you no longer need:
# See sizes of all cached models, sorted largest first
du -sh ~/.cache/huggingface/hub/*/ | sort -rh
# Example output:
# 26G /home/ubuntu/.cache/huggingface/hub/models--meta-llama--Llama-2-13b-hf/
# 14G /home/ubuntu/.cache/huggingface/hub/models--mistralai--Mistral-7B-v0.1/
# 1.7G /home/ubuntu/.cache/huggingface/hub/models--openai--clip-vit-large-patch14/
# 0.4G /home/ubuntu/.cache/huggingface/hub/models--bert-base-uncased/
# Delete a single model directory (this is safe and reversible — re-run from_pretrained to re-download)
rm -rf ~/.cache/huggingface/hub/models--meta-llama--Llama-2-13b-hf/
# Verify the space was recovered
df -h ~
You can also clear the entire cache if you want a clean slate. Next time you call from_pretrained(), the relevant model will be re-downloaded:
# Nuclear option — clears everything
rm -rf ~/.cache/huggingface/hub/
# The parent directory is recreated automatically on next use
One important caveat: the blobs directory uses hard links to deduplicate files shared across revisions of the same model. Deleting an entire model directory is always safe. However, do not delete individual files inside the blobs/ subdirectory manually, as other snapshots of the same model may depend on them. Always delete at the model directory level.
This approach is ideal when you cannot change your code or environment variables but do have a larger disk mounted elsewhere. You move the cache directory to the larger partition and leave a symlink in its original location. From the operating system's perspective, any write to ~/.cache/huggingface/ is transparently redirected to the larger disk.
# Step 1: Create the target directory on the larger partition
mkdir -p /data/huggingface_cache
# Step 2: Move the existing cache to the new location (preserves your downloads)
# This may take a few minutes if the cache is large
mv ~/.cache/huggingface/ /data/huggingface_cache/
# Step 3: Create a symlink in the original location pointing to the new one
ln -s /data/huggingface_cache/huggingface ~/.cache/huggingface
# Step 4: Verify the symlink is correct
ls -la ~/.cache/ | grep huggingface
# lrwxrwxrwx 1 ubuntu ubuntu 34 Jul 16 09:12 huggingface -> /data/huggingface_cache/huggingface
# Step 5: Confirm reads and writes go to the new disk
df -h ~/.cache/huggingface/hub/
# Filesystem Size Used Avail Use% Mounted on
# /dev/sdb1 500G 48G 428G 10% /data
If you prefer to start fresh rather than move existing files:
# Alternative: delete the old cache, create symlink to empty target
rm -rf ~/.cache/huggingface/
mkdir -p /data/huggingface_cache/huggingface
ln -s /data/huggingface_cache/huggingface ~/.cache/huggingface
No environment variable changes are needed. No code changes are needed. All tools — transformers, diffusers, datasets, sentence-transformers — follow the symlink automatically.
For Docker-based workflows, the equivalent approach is to mount the large disk into the container at the cache path:
# Mount /data/huggingface_cache from the host into the container
docker run --gpus all \
-v /data/huggingface_cache:/root/.cache/huggingface \
my-ml-image \
python train.py
For a targeted, code-level fix that does not require any system configuration, pass cache_dir directly to from_pretrained(). This overrides the default cache location for that single call, regardless of where HF_HOME is set.
from transformers import AutoModelForCausalLM, AutoTokenizer
# Specify a cache directory on a partition with sufficient space
CACHE_DIR = "/data/hf_cache"
model = AutoModelForCausalLM.from_pretrained(
"mistralai/Mistral-7B-v0.1",
cache_dir=CACHE_DIR
)
tokenizer = AutoTokenizer.from_pretrained(
"mistralai/Mistral-7B-v0.1",
cache_dir=CACHE_DIR
)
The same parameter works across the HuggingFace ecosystem:
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, pipeline
from diffusers import StableDiffusionPipeline
from sentence_transformers import SentenceTransformer
from datasets import load_dataset
import torch
CACHE = "/data/hf_cache"
# transformers — any AutoClass
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/bart-large-cnn", cache_dir=CACHE)
tokenizer = AutoTokenizer.from_pretrained("facebook/bart-large-cnn", cache_dir=CACHE)
# transformers — pipeline shorthand
pipe = pipeline("summarization", model="facebook/bart-large-cnn", model_kwargs={"cache_dir": CACHE})
# diffusers — Stable Diffusion and related models
sd_pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
cache_dir=CACHE
)
# datasets — large NLP datasets
dataset = load_dataset("wikipedia", "20220301.en", cache_dir=CACHE)
# huggingface_hub — direct file downloads
from huggingface_hub import hf_hub_download
local_path = hf_hub_download(
repo_id="meta-llama/Llama-2-7b-hf",
filename="tokenizer.model",
cache_dir=CACHE
)
If you use this pattern across a large codebase, centralise the value in a single config constant rather than scattering the path literal everywhere:
# config.py
import os
HF_CACHE_DIR = os.environ.get("HF_CACHE_DIR", "/data/hf_cache")
# any other module
from config import HF_CACHE_DIR
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", cache_dir=HF_CACHE_DIR)
This way switching the cache location across your whole project requires changing one line in one file, or setting a single environment variable at runtime.
Before deleting anything, it is worth scanning the cache to understand exactly what is there, how large each item is, and when it was last accessed. The huggingface_hub.scan_cache_dir() function gives you that information as structured Python objects.
from huggingface_hub import scan_cache_dir
cache = scan_cache_dir()
# Top-level summary
print(f"Cache location : {cache.cache_dir}")
print(f"Total size : {cache.size_on_disk_str}")
print(f"Cached repos : {len(cache.repos)}")
print(f"Warnings : {len(cache.warnings)}")
print()
# Per-model breakdown
print(f"{'Model':<55} {'Size':>10} {'Revisions':>9} {'Last used'}")
print("-" * 100)
for repo in sorted(cache.repos, key=lambda r: r.size_on_disk, reverse=True):
print(
f"{repo.repo_id:<55} "
f"{repo.size_on_disk_str:>10} "
f"{len(repo.revisions):>9} "
f"{repo.last_accessed_str}"
)
Cache location : /home/ubuntu/.cache/huggingface/hub
Total size : 48.5 G
Cached repos : 4
Warnings : 0
Model Size Revisions Last used
----------------------------------------------------------------------------------------------------
meta-llama/Llama-2-13b-hf 26.0 G 1 14 days ago
mistralai/Mistral-7B-v0.1 14.1 G 1 2 days ago
openai/clip-vit-large-patch14 1.7 G 1 3 days ago
bert-base-uncased 0.4 G 2 5 hours ago
For a quick one-liner that prints total cache size to stdout:
python -c "from huggingface_hub import scan_cache_dir; c = scan_cache_dir(); print(c.size_on_disk_str)"
To list individual files within a model snapshot (useful if you only cached some shards of a sharded model and want to identify incomplete downloads):
from huggingface_hub import scan_cache_dir
import pathlib
cache = scan_cache_dir()
for repo in cache.repos:
if repo.repo_id == "mistralai/Mistral-7B-v0.1":
for revision in repo.revisions:
print(f"Revision: {revision.commit_hash[:12]}")
print(f" Size : {revision.size_on_disk_str}")
print(f" Files :")
for f in sorted(revision.files, key=lambda x: x.size_on_disk, reverse=True):
size_mb = f.size_on_disk / (1024 ** 2)
print(f" {f.file_name:<50} {size_mb:>8.1f} MB")
Revision: 7231864981
Size : 14.1 G
Files :
model-00001-of-00002.safetensors 7322.1 MB
model-00002-of-00002.safetensors 7007.3 MB
tokenizer.model 0.5 MB
tokenizer.json 1.8 MB
config.json 0.0 MB
generation_config.json 0.0 MB
model.safetensors.index.json 0.1 MB
special_tokens_map.json 0.0 MB
tokenizer_config.json 0.0 MB
| Situation | Best fix | Effort |
|---|---|---|
| You have a second disk or data partition available | Set HF_HOME in .bashrc |
One-time, 2 commands |
| Old models are taking up space you no longer need | huggingface-cli delete-cache or rm -rf model dir |
Minutes |
| Cannot change env vars (shared server, Docker entrypoint) | Symlink ~/.cache/huggingface to larger partition |
Three commands |
| Need a one-off fix for a single script without touching the system | from_pretrained(..., cache_dir="/data/hf_cache") |
One line of code |
| Running Docker with a volume mount | Mount the large disk at /root/.cache/huggingface |
One Docker flag |
OSError: [Errno 28] No space left on device during from_pretrained() means the partition hosting ~/.cache/huggingface/ is full — the error occurs at the file write step inside shutil.copyfileobj.du -sh ~/.cache/huggingface/hub/*/ to see which models are consuming space.export HF_HOME=/data/huggingface_cache in ~/.bashrc redirects all future downloads to a larger partition.huggingface-cli delete-cache shows an interactive TUI listing models by size. Select and delete what you no longer need.~/.cache/huggingface to the larger disk — fully transparent to all HuggingFace tools.cache_dir="/data/hf_cache" to any from_pretrained() call.huggingface_hub.scan_cache_dir() in Python to audit cache contents programmatically before deleting anything.Once the cache is on a large enough partition, you will not see this error again — the download completes, the model is cached, and subsequent loads are instant without re-downloading.