Why a local model path still tries to reach HuggingFace, and how to load fully offline
OSError: We couldn't connect to 'https://huggingface.co' to load this model and it looks like ... is not the path to a directory containing a config.json file
Also appears as
- requests.exceptions.ConnectionError: HTTPSConnectionPool(host='huggingface.co', port=443)
- ValueError: Connection error, and we cannot find the requested files in the cached path
- Model loads config from local path but still attempts a network call for a sub-component
Short answer
Passing a local path to from_pretrained does not guarantee an offline load, because transformers and related libraries (tokenizers, some model configs, auto-mapping code) can still issue background network calls to check for updates, fetch a referenced remote component, or resolve auto_map entries that point back at the original HuggingFace repo. The fix is to set HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 explicitly, use a complete local snapshot directory (not just the weights file), and verify no config field still references a remote repo ID.
Affects: Air-gapped or network-isolated environments loading models from local disk, transformers/huggingface_hub of any recent version
Fix it in a few minutes
- 1Set both offline environment variables before running anything: export HF_HUB_OFFLINE=1 and export TRANSFORMERS_OFFLINE=1.
- 2Ensure your local directory is a complete snapshot: config.json, tokenizer files, and all weight shards, not just the .safetensors files copied alone.
- 3Load explicitly from the local directory path, not a repo ID string, so there is no ambiguity about intending a remote lookup.
- 4Check config.json and tokenizer_config.json for an auto_map field referencing a remote repo ID; if present and trust_remote_code is used, that remote code fetch will still attempt a network call unless it too is fully vendored locally.
- 5Test the exact load call with network access physically or firewall-disabled to confirm it truly succeeds offline before shipping to the air-gapped environment.
How to confirm this is your problem
- Loading from what looks like a valid local directory still raises a connection or timeout error
- The failure only appears in the air-gapped or firewalled environment, not on a connected development machine using the identical code
- Some components (base model weights) load fine while a specific piece (a referenced processor, a remote code file, a specific config sub-field) triggers the network attempt
- The error message explicitly names huggingface.co as the unreachable host despite a local path being passed
Root causes and fixes
HF_HUB_OFFLINE / TRANSFORMERS_OFFLINE environment variables not set, so the library still attempts to check for updates
By default, huggingface_hub and transformers try to reach the Hub first to check whether cached files are up to date (an ETag/metadata check), only falling back to local cache after that attempt times out or fails, which can be slow and, in a fully air-gapped network with no DNS resolution at all, can hang or fail hard rather than falling back gracefully. Explicit offline mode skips this network check entirely and goes straight to local files.
Fix: Export HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 in the environment before any Python process starts, or set them programmatically at the very top of your script before importing transformers.
export HF_HUB_OFFLINE=1 export TRANSFORMERS_OFFLINE=1
Local directory is an incomplete snapshot, missing config or tokenizer files that were never copied alongside the weights
It is common to manually copy only the large weight files (.safetensors) to an air-gapped target while forgetting smaller companion files like config.json, tokenizer.json, tokenizer_config.json, special_tokens_map.json, or generation_config.json. When any of these is missing, transformers falls back to trying to fetch it remotely, which fails hard with no network available.
Fix: Always transfer the complete snapshot_download output directory (or use huggingface-cli download --local-dir to get one deliberately), not a hand-picked subset of files, so every file the loader might need is present locally.
huggingface-cli download org/model --local-dir ./model-snapshot
config.json or tokenizer_config.json contains an auto_map or custom class reference pointing back at a remote repo
Models using trust_remote_code often have an auto_map field in their config that maps class names to a module path within their original HuggingFace repo. Even with the weights fully local, loading such a model with trust_remote_code=True can still trigger a fetch of that referenced Python module from the remote repo unless that code has also been fully localized.
Fix: For trust_remote_code models bound for an air-gapped environment, download the custom Python modeling files explicitly as part of the snapshot and verify the auto_map paths resolve locally, or vendor the code into your own package entirely to remove the dependency on remote resolution.
python -c "import json; print(json.load(open('config.json')).get('auto_map'))"A downstream library beyond transformers itself (a tokenizer backend, an evaluation harness, a RAG embedding step) makes its own independent network call
Some libraries built on top of transformers or huggingface_hub perform their own separate download or version-check calls that are not covered by TRANSFORMERS_OFFLINE alone, since that variable only affects transformers' own logic, not every library in a larger pipeline that happens to also touch the Hub.
Fix: Trace exactly which library and call is making the network attempt (via a traceback or by tracing socket connections) and check whether that specific library has its own offline environment variable or requires an explicit local path argument.
python -X importtime script.py 2> import_trace.log
DNS resolution attempt itself hangs for a long time before failing, making the environment appear stalled rather than clearly erroring
In a fully air-gapped network with no DNS server configured at all (rather than DNS working but the destination being unreachable), a network call can hang for the full OS-level DNS timeout before failing, making an offline-mode misconfiguration look like a hang or extreme slowness rather than an immediate, clear connection error.
Fix: Confirm DNS and outbound network are both fully disabled or fully enabled consistently in your test environment, since a half-configured network (DNS works, TCP connect fails) produces much longer, more confusing failure modes than either state alone.
Diagnostic commands
Confirm offline mode is actually active
python -c "import os; print(os.environ.get('HF_HUB_OFFLINE'), os.environ.get('TRANSFORMERS_OFFLINE'))"If either prints None, that offline flag was not actually set in the process's environment, which is the most common root cause of an unexpected network attempt.
List exactly which files are present in the local snapshot
ls -la ./model-snapshot
Compare this file list against a complete snapshot_download of the same model on a connected machine; any missing file (especially config.json, tokenizer files, or generation_config.json) is a likely trigger for a fallback network call.
Test the exact load with network forcibly blocked
python -c "import socket; socket.setdefaulttimeout(1); from transformers import AutoModelForCausalLM; AutoModelForCausalLM.from_pretrained('./model-snapshot')"A fast failure or hang here, even on a connected machine, reproduces the air-gapped failure mode locally and lets you iterate on the fix without needing access to the actual isolated environment.
Stopping it from happening again
- Standardize a deployment process that always uses huggingface-cli download --local-dir (or snapshot_download) to produce a complete, verified snapshot directory, never a manual partial file copy.
- Bake HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 into the base container image or systemd unit used in air-gapped environments, so it is never accidentally left unset.
- For any trust_remote_code model destined for air-gapped use, explicitly vendor its custom Python files into your own controlled location rather than depending on auto_map resolution working offline.
- Test every model's full load path with network access disabled in a staging environment before shipping it to the actual air-gapped target, to catch missing files or lingering network dependencies early.
When this becomes an architecture problem
If you are regularly onboarding new models into a genuinely air-gapped environment, this stops being a per-model troubleshooting exercise and becomes a standardized ingestion pipeline: verified snapshot download, completeness check, offline-mode smoke test, then transfer. Building that pipeline once removes this entire class of failure going forward.
Frequently asked questions
Does setting HF_HUB_OFFLINE=1 break loading from a repo ID string instead of a local path?
No, if the model is already fully cached locally under the standard huggingface_hub cache directory from a prior connected download, offline mode will find and use that cache when you reference the same repo ID, it simply skips the network freshness check rather than requiring a literal local directory path.
Why does the base model load offline but a LoRA adapter or processor fails?
Each component (base model, adapter, image processor, tokenizer) is typically loaded via its own from_pretrained call and its own local cache entry or directory; if only the base model's snapshot was transferred to the air-gapped environment and the adapter's files were not, that specific piece will still attempt a network fetch and fail.
Is there a way to detect all network dependencies before deploying to an air-gapped site?
Run your exact loading code in a staging environment with network access blocked at the firewall level (not just unset environment variables) and treat any error or hang as a dependency that needs to be resolved before the real air-gapped deployment.
Do quantized or GGUF models have the same offline-loading concerns?
GGUF models loaded through llama.cpp-based tools are generally more self-contained since the tokenizer vocabulary is embedded in the file itself, reducing the number of separate companion files needed, but any wrapper library that still checks HuggingFace for model cards or metadata can introduce the same class of network dependency.
Size it properly next time
Free calculators that prevent this class of failure before you provision hardware.
Air-Gapped LLM Deployment Checklist
A practical control checklist for deploying and maintaining large language models in a fully air-gapped environment, from initial staging through ongoing patching and drift detection.
Free ToolOn-Prem AI Deployment Checklist
A 30-point pre-deployment checklist covering use cases, hardware, security, model operations, and rollout for self-hosted enterprise LLMs.
Free ToolEdge AI Deployment Readiness Assessment
Score your organization across eight dimensions of edge AI readiness, from hardware validation and update strategy to connectivity resilience and fleet monitoring.
Related problems
401/403 Unauthorized pulling a gated model from HuggingFace
A 401 or 403 on a gated HuggingFace repo means the request reached the Hub but was rejected for authorization, not because the model does not exist. The three real causes are: you have not accepted the model's license on the web page with the account tied to your token, the token exists but was created without read access to gated repos, or the token is valid but was never actually passed to the download call (no HF_TOKEN in the environment, no login run). Fix by accepting the license, generating a token with the right scope, and exporting it where the client library will find it.
Corrupted model checkpoint fails to load or loads with garbage weights
A corrupted checkpoint means the bytes on disk do not match the original artifact the model author published, whether from an interrupted download, a bad copy between systems, disk-level bit rot, or a failed write during a save operation. There is no reliable way to repair a corrupted deep learning checkpoint; the fix is always to verify the file against a known-good hash or size and re-obtain a clean copy, then build a verification step into your pipeline so the same failure does not silently recur.
trust_remote_code required, and the security tradeoff behind that error
This error is transformers deliberately refusing to run arbitrary Python code from a model repository without explicit consent, because loading such a model means executing the repository author's custom modeling_*.py file directly in your process with full permissions, not just deserializing tensor data. Passing trust_remote_code=True removes the error but does not remove the risk; in a regulated or air-gapped environment the correct approach is to review that code yourself, vendor a pinned copy of it, and only then load with trust_remote_code=True against your reviewed copy.
Model revision or commit not found when pinning a specific version
A revision not found error means the exact commit hash, branch name, or tag you specified does not exist in that repository, most often because it was copied from a different repo, mistyped, or refers to a commit that was later force-pushed away or a tag that was deleted or renamed by the repo maintainer. Fix it by listing the repo's actual available revisions and re-pinning to a real, current one, and build your own immutable mirror if you need guarantees beyond what the source repo's maintainers commit to preserving.
GuideAir-Gapped LLM Deployment Patterns That Actually Work
Air-gapped LLM deployment patterns that work: offline model transfer, update workflows, monitoring without telemetry, and CMMC-ready architectures.
GuideOn-Prem LLM Deployment Architecture: Reference Guide
Reference architecture for on-prem LLM deployment: inference servers, GPU sizing, RAG pipelines, and security zones for regulated manufacturers.
GuideSecuring Model Weights in the Enterprise
Secure model weights end to end: custody controls, encryption at rest, access policies, and exfiltration prevention for regulated AI deployments.
GuideAir-Gapped Model Updates: A Patching Guide
Air-gapped model updates for enterprise AI: secure transfer procedures, hash verification, and staged rollout so patches never introduce risk.
Still stuck, or tired of fighting your own infrastructure?
Netray deploys and operates on-prem AI for regulated manufacturers and defense suppliers. We have debugged this stack in production, on air-gapped networks, at scale.