Skip to content
Boomspot
  • Home
Loading...
Boomspot

Daily tech news, software development coverage, Apple reporting, and the gear behind modern music making.

TwitterLinkedIn

Browse

  • Categories
  • Tags
  • Authors

Company

  • About
  • Contact

Legal

  • Privacy Policy
  • Terms of Service
  • Unsubscribe

© 2026 Boomspot. All rights reserved.

Built by Boomspot
Updated hourly

AI Content Disclosure: Articles on Boomspot are researched, written, and edited with the assistance of advanced AI systems. We combine software-assisted research with editorial oversight to deliver useful, accurate, and practical technical and music production content. Learn more about our editorial approach.

Browse by Category

Technology663Coding179Linux53SEO51Music Production34Studio Gear31Apple Rumors11

Popular Posts

Raspberry Pi 5 Alternatives After the $77.50 Price Hike

Raspberry Pi 5 Alternatives After the $77.50 Price Hike

6 min read
GamesSoundCon 2026: Worth It for Composers?

GamesSoundCon 2026: Worth It for Composers?

6 min read
Why External Hard Drive Prices Are Skyrocketing in 2026

Why External Hard Drive Prices Are Skyrocketing in 2026

5 min read
ROCm or Vulkan for llama.cpp on AMD GPUs? How to Decide

ROCm or Vulkan for llama.cpp on AMD GPUs? How to Decide

8 min read
Which Ethernet Cable Category Do You Actually Need?

Which Ethernet Cable Category Do You Actually Need?

6 min read

Recent Posts

Google Indexing API Alternative for Job Postings: 5 Steps

Google Indexing API Alternative for Job Postings: 5 Steps

Oct 24, 2026•8 min
How to Move From Quickstart to Production (Checklist)

How to Move From Quickstart to Production (Checklist)

Oct 24, 2026•9 min
Tape Saturation vs Cassette Plugins: Which Do You Need?

Tape Saturation vs Cassette Plugins: Which Do You Need?

Oct 24, 2026•9 min
How to Label Free Articles on a Paywalled Site: Test Plan

How to Label Free Articles on a Paywalled Site: Test Plan

Oct 24, 2026•8 min
S3 Gateway Endpoint vs Interface Endpoint: Which to Pick

S3 Gateway Endpoint vs Interface Endpoint: Which to Pick

Oct 24, 2026•9 min
  1. Home
  2. Coding
  3. How to Safely Load a PyTorch Checkpoint From Hugging Face
coding9 min read

How to Safely Load a PyTorch Checkpoint From Hugging Face

A stranger's best.pt can run code the moment you load it. Here is how to check a checkpoint first, load it with weights_only=True, and fix Unsupported global errors safely.

S

Staff

October 24, 2026

Reviewed byDorian

How to Safely Load a PyTorch Checkpoint From Hugging Face

A .pt file you found through a search result is a small program, and the pickle loader runs it for you. Most of the time that program just rebuilds some tensors. You can't know that from the file name.

This guide walks you through checking and loading a downloaded checkpoint without giving it permission to run arbitrary code. You will inspect the pickle first, load it with weights_only=True, fix the "Unsupported global" error the right way, and handle YOLO best.pt files.

The problem is not shrinking. A post on dev.to, first published on blog.peng.ly, counted Hugging Face uploaders who published only pickle files (.pt, .pth, .ckpt or .pkl, with no safetensors, GGUF or ONNX alongside). Its author puts the share at about one in seventeen in the second half of 2024 and about one in eight since March. Those figures are one author's analysis of Hub data, not this blog's research.

Versions and labeling. Every code block below is unexecuted: nobody ran it while writing this article, and the "expected output" lines are predictions, not captured logs. The snippets assume Python 3.10 or later, PyTorch 2.6 or later (the release where, per the post, torch.load began restricting unpickling by default), and NumPy 2.x names. The Ultralytics package is needed only for Step 5, and the source does not name the version that introduced its safe mode.

Step 1: Know what you are guarding against

A pickle is not a data format so much as a list of instructions. It can tell Python to import any module and call any function with chosen arguments. Loading the file executes those instructions, so a malicious checkpoint can run code before you ever see a tensor.

weights_only=True swaps in a restricted unpickler. According to the post, since PyTorch 2.6 torch.load unpickles only tensors and a short list of harmless types unless you say otherwise. Anything else makes the load fail instead of run.

That matters for the decision you face. If a file loads under the restricted unpickler, the pickle inside it is mostly irrelevant. If it fails, you have learned something useful about what the file wants.

Step 2: Inspect the pickle without running it

Python's pickletools can read the opcodes in a pickle without executing them. A checkpoint saved by torch.save is a zip archive, and the pickle sits in a data.pkl entry. The tensor bytes live in separate entries, so reading the pickle is cheap.

The post's author used this approach, with ranged requests so that no multi-gigabyte download was needed. For a file already on disk, this is enough:

## UNEXECUTED example. Python 3.10+, standard library only.
import pickletools
import sys
import zipfile

def list_globals(path):
    with zipfile.ZipFile(path) as z:
        name = next(n for n in z.namelist() if n.endswith('data.pkl'))
        data = z.read(name)
    found = set()
    strings = []
    for op, arg, _pos in pickletools.genops(data):
        if op.name in ('SHORT_BINUNICODE', 'BINUNICODE', 'UNICODE', 'BINUNICODE8'):
            strings.append(arg)
        elif op.name == 'GLOBAL':
            found.add(arg.replace(' ', '.'))
        elif op.name == 'STACK_GLOBAL' and len(strings) >= 2:
            found.add(strings[-2] + '.' + strings[-1])
    return sorted(found)

for g in list_globals(sys.argv[1]):
    print(g)

Run it as python inspect_pt.py model.pt. For a plain state_dict, the expected output (a prediction, not a captured run) is a short list of PyTorch internals:

collections.OrderedDict
torch._utils._rebuild_tensor_v2
torch.FloatStorage

The STACK_GLOBAL branch is a heuristic. It assumes the module and name strings were pushed most recently, and pickles that reuse memoized strings can fool it. Treat the output as a triage aid, and let the restricted loader in Step 3 be the real gate.

Failure case for this script: if the file is not a zip (an old-format checkpoint, or a raw .pkl), zipfile.BadZipFile is raised. Treat that as a reason to ask the uploader for a safetensors version rather than a reason to load it anyway.

What you are looking for is names that have no business in a checkpoint. In the post's sample of 114 files, none asked for anything like os or eval. The author's point still stands: you can't tell without looking, and most people look by loading.

Step 3: Load with weights_only=True and verify

Explicitly pass the flag. Do not rely on the default, because older environments and wrapper libraries behave differently. We cover related ground in how to draft customer support emails with ollama locally explained.

## UNEXECUTED example. torch>=2.6
import torch

state = torch.load('model.pt', map_location='cpu', weights_only=True)
print(type(state))
print(list(state)[:3])

Expected output for a typical state_dict (prediction): <class 'dict'> followed by the first few parameter names, such as ['conv1.weight', 'conv1.bias', 'bn1.weight'].

Verification, part one: load into a model with matching architecture using model.load_state_dict(state, strict=True). A clean result means the keys and shapes match. Some checkpoints nest weights under a key like state_dict, so you may need state['state_dict'].

Verification, part two: confirm the protection is actually on. This probe saves a harmless object whose pickle tries to call print:

## UNEXECUTED example. Harmless probe, never load files you did not create like this.
import torch

class Probe:
    def __reduce__(self):
        return (print, ('code ran during load',))

torch.save({'w': Probe()}, 'probe.pt')
torch.load('probe.pt', weights_only=True)

The expected result is an UnpicklingError that mentions builtins.print as an unsupported global, and the text "code ran during load" never appears. If that text prints, your loader is not restricting anything.

In the post's sample, 89 of 114 checkpoints (one random pickle-only repo per uploader, created between August and 21 October) were a state_dict and perhaps an epoch number, and loaded fine this way. That is one author's count, but it suggests the restricted load is the right first attempt.

Step 4: Fix "Unsupported global" without turning protection off

The other 25 files in that sample failed. Ten failed over something mundane, such as a NumPy float holding the best accuracy or the argparse settings saved during training. The post shows torch 2.14 printing this, trimmed: This pairs well with build a streamlit chatbot with openrouter free models in depth.

Weights only load failed. [...]
  (1) [...] Re-running `torch.load` with `weights_only` set to `False`
  will likely succeed, but it can result in arbitrary code execution.
  (2) Alternatively, to load with `weights_only=True` please check
  the recommended steps in the following error message.
  WeightsUnpickler error: Unsupported global: GLOBAL
  numpy._core.multiarray.scalar was not an allowed global by default.

Option 1 is listed first and promises success. It also switches off the only thing between you and the file's code. Take option 2: allow the one named type and nothing else.

## UNEXECUTED example. torch>=2.6, numpy 2.x
import numpy as np
import torch

torch.serialization.add_safe_globals([np._core.multiarray.scalar])
state = torch.load('ckpt.pt', map_location='cpu', weights_only=True)
print(state['best_acc'])

Expected output (prediction): the stored accuracy value prints. Use the exact name from your own error message, since NumPy 1.x uses numpy.core instead of numpy._core. A NumPy scalar may also trigger a second error naming another type. Repeat the process one global at a time, and read each name before you allow it.

Allow types like NumPy scalars or an argparse namespace. Refuse anything that can launch processes or evaluate strings, such as os.system, subprocess.Popen or builtins.eval. That is a judgment call from this article, not a rule from the source.

Step 5: Handle YOLO best.pt files

Eight of the 114 sampled files were whole YOLO models, pickled with their Ultralytics classes, usually named best.pt. You never see torch's error with these, because per the post the Ultralytics loader calls torch.load with weights_only=False unless you ask otherwise.

The post says that since June there has been an opt-in safe mode that loads with weights_only=True and an allowlist of Ultralytics' own classes. Turn it on with an environment variable:

Also read: see validate csv upload encoding in javascript, step by step

## UNEXECUTED example. Requires an Ultralytics release that includes safe mode.
ULTRALYTICS_SAFE_LOAD=1 python detect.py

Without the variable, per the same post, a stranger's best.pt runs whatever it contains. Verify the setting by checking that the variable is present in the process that calls YOLO('best.pt'). The source does not say what error appears when safe mode rejects a file, so treat any refusal as a reason to stop, not to retry with the flag removed.

Step 6: Decide what to do with the file

Work through these in order:

  1. It loads with weights_only=True. Use it. Optionally convert it, as below, so you never repeat the exercise.
  2. It fails on one or two named, ordinary types. Review each name, then allow it with add_safe_globals.
  3. It names a class from the author's training code, such as a custom model class, a LeRobot policy config or a DeepSpeed object. The post counted seven of these. They will not load without that code installed, and installing a stranger's code is the same risk. Reject the file, or inspect it inside a throwaway container or VM with no network and no credentials.
  4. It is a YOLO file. Set ULTRALYTICS_SAFE_LOAD=1 every time.
  5. It imports anything process- or eval-related. Delete it and ask the uploader for a safetensors version.

Once you have a safely loaded tensor dict, you can write your own safetensors copy:

## UNEXECUTED example. pip install safetensors
from safetensors.torch import save_file
save_file(state, 'model.safetensors')

This works only for a flat dict of tensors. Nested dicts or shared tensors need flattening first.

What to expect next

Expect more of these files, not fewer. The post reports pickle-only uploaders at roughly 3,300 a month from March to September, mostly newcomers whose repos rarely declare a library, and its author could not explain why the share dipped in October. Expect most checkpoints to pass Step 3, a minority to need one allowlisted type, and a few to demand code you should not run. Run the inspection script first, and the restricted loader will do the rest.

Tags

Artificial IntelligenceMachine LearningCybersecurityCoding Best PracticesOpen Source

Keep reading

WebAssembly: Unleashing Native Speed in Web Browsers
Coding•4 min read

WebAssembly: Unleashing Native Speed in Web Browsers

WebAssembly is transforming web development with near-native performance, enabling more complex and efficient applications.

Sep 6, 2025

Revolutionizing Code with GitHub Copilot X
Coding•3 min read

Revolutionizing Code with GitHub Copilot X

GitHub Copilot X revolutionizes software development, offering AI-driven pair programming to enhance efficiency, learning, and code quality.

Sep 6, 2025

Why Rust is Overtaking C++ in the Programming World
Coding•3 min read

Why Rust is Overtaking C++ in the Programming World

Rust is challenging C++ dominance in software development with its focus on memory safety, speed, and concurrency.

Sep 6, 2025

More stories for your next project

Get tech, coding, and music production updates in your inbox.

Unsubscribe anytime.