huggingface/transformers · error · AssertionError
Provided path ({save_directory}) should be a directory, not
Error message
Provided path ({save_directory}) should be a directory, not a file What it means
FeatureExtractorBase.save_pretrained expects a directory to write preprocessor_config.json into. If save_directory points at an existing file, writing would clobber it, so os.path.isfile triggers an immediate AssertionError before makedirs.
Source
Thrown at src/transformers/feature_extraction_utils.py:399
return cls.from_dict(feature_extractor_dict, **kwargs)
def save_pretrained(self, save_directory: str | os.PathLike, push_to_hub: bool = False, **kwargs):
"""
Save a feature_extractor object to the directory `save_directory`, so that it can be re-loaded using the
[`~feature_extraction_utils.FeatureExtractionMixin.from_pretrained`] class method.
Args:
save_directory (`str` or `os.PathLike`):
Directory where the feature extractor JSON file will be saved (will be created if it does not exist).
push_to_hub (`bool`, *optional*, defaults to `False`):
Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
namespace).
kwargs (`dict[str, Any]`, *optional*):
Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
"""
if os.path.isfile(save_directory):
raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")
os.makedirs(save_directory, exist_ok=True)
if push_to_hub:
commit_message = kwargs.pop("commit_message", None)
repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])
repo_id = hf_api().create_repo(repo_id, exist_ok=True, **kwargs).repo_id
files_timestamps = self._get_files_timestamps(save_directory)
# If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
# loaded from the Hub.
if self._auto_class is not None:
custom_object_save(self, save_directory, config=self)
# If we save using the predefined names, we can load using `from_pretrained`
output_feature_extractor_file = os.path.join(save_directory, FEATURE_EXTRACTOR_NAME)
self.to_json_file(output_feature_extractor_file)View on GitHub (pinned to a597f97485)
Solutions
- Pass the directory: fe.save_pretrained('./my-extractor') — the JSON filename is chosen automatically
- If the path exists as a file by mistake, remove/rename it first
- To control the filename, save into a directory and rename the emitted preprocessor_config.json afterwards
Example fix
# before
fe.save_pretrained("checkpoints/preprocessor_config.json")
# after
fe.save_pretrained("checkpoints") Defensive patterns
Strategy: validation
Validate before calling
import os
def ensure_dir(path):
if os.path.isfile(path):
raise ValueError(f"{path} is a file; pass its parent directory")
os.makedirs(path, exist_ok=True)
return path Type guard
def is_directory_path(path) -> bool:
import os
return not os.path.isfile(path) Try / catch
try:
fe.save_pretrained(path)
except AssertionError as e:
if "should be a directory" in str(e):
import os
fe.save_pretrained(os.path.dirname(path))
else:
raise Prevention
- Pass folders, never filenames, to save_pretrained
- Create and verify the output directory before saving
- Standardize on one helper for all save paths in the pipeline
When it happens
Trigger: Calling fe.save_pretrained(path) where path is a file — commonly passing the intended JSON filename itself (e.g. 'config.json') instead of its parent folder, or a path created by an earlier file write.
Common situations: Confusion between 'save to this file' vs 'save into this directory' APIs; scripts that create the target path as a file first; typos where the filename is used as the directory.
Related errors
- You should supply an instance of `transformers.BatchFeature`
- type of {first_element} unknown: {type(first_element)}. Shou
- Some items in the output dictionary have a different batch s
- Invalid padding strategy:{padding_side}
- When setting ``truncation=True``, make sure that ``max_lengt
AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14).
Data as JSON: /api/errors/52d9eb733fdcc2dd.
Report an issue: GitHub.