Skip to content

Fix DatasetDict.push_to_hub leaving removed splits in the dataset card - #8367

Merged
lhoestq merged 1 commit into
huggingface:mainfrom
pjh4993:fix/ghi-3-hub-remove-stale-split-patterns
Jul 28, 2026
Merged

Fix DatasetDict.push_to_hub leaving removed splits in the dataset card#8367
lhoestq merged 1 commit into
huggingface:mainfrom
pjh4993:fix/ghi-3-hub-remove-stale-split-patterns

Conversation

@pjh4993

@pjh4993 pjh4993 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Pushing a DatasetDict that drops a split leaves the repo unloadable:

DatasetDict({"train": ds_train, "test": ds_test}).push_to_hub("user/repo")
DatasetDict({"train": ds_train}).push_to_hub("user/repo")   # "test" is gone

load_dataset("user/repo")
# ValueError: Couldn't infer the same data file format for all splits.
# Got {'train': ('parquet', {}), 'test': (None, {})}

Context

Two things matter here:

  • configs.data_files paths are globs, and every split listed there must expand to real files at load time.
  • DatasetDict.push_to_hub replaces the split set: any split not in the dict has its parquet files deleted from the repo, and the card is rewritten with remove_other_splits=True. (Dataset.push_to_hub only appends, and passes remove_other_splits=False.)

After the second push above, the card's YAML header looks like this:

configs:
- config_name: default
  data_files:
  - split: train
    path: data/train-*
  - split: test           # <-- stale: this push just deleted these files
    path: data/test-*
dataset_info:
  splits:
  - name: train           # <-- dataset_info correctly dropped "test"

data/test-* now matches no files, so load_dataset can't infer a format for test and fails.

Root cause

remove_other_splits=True was only honored for the dataset_info block. The configs.data_files block was rebuilt like this:

data_files_to_dump = sanitize_patterns(metadata_config["data_files"])  # start from the old card
for split_info in splits_info:                                         # then add this push's splits
    data_files_to_dump[split_info.name] = [f"{data_dir}/{split_info.name}-*"]

Splits are only ever added to that dict — nothing removes one, so test survives from the old card even though this push deleted its files.

Fix

When remove_other_splits=True, don't seed from the old card — start empty so the patterns describe exactly the splits this push wrote.

if "data_files" in metadata_config and not remove_other_splits:

Dataset.push_to_hub is unaffected — it stays on the additive path and keeps whatever the card already lists.

Tests

Two hermetic tests in tests/test_buckets.py (in-memory filesystems, no Hub), alongside the existing _get_updated_dataset_card test:

  • test_get_updated_dataset_card_drops_removed_splits_when_replacing_split_set — verified to fail before the fix. Asserts both blocks agree, since it's the disagreement that breaks loading.
  • test_get_updated_dataset_card_keeps_existing_splits_when_appending — pins the additive remove_other_splits=False path so Dataset.push_to_hub doesn't regress.

…lit set

DatasetDict.push_to_hub deletes the shards of splits that are no longer in
the dict, but _get_updated_dataset_card only applied remove_other_splits to
the dataset_info block. The configs.data_files patterns were still seeded
from the existing card and splits were only ever added, so a removed split
kept its pattern with no files behind it, making the dataset unloadable:

    ValueError: Couldn't infer the same data file format for all splits.
    Got {'train': ('parquet', {}), 'test': (None, {})}

Skip the seeding when remove_other_splits is set so the patterns describe
only the splits this push wrote. Dataset.push_to_hub passes
remove_other_splits=False and keeps its additive behaviour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pjh4993
pjh4993 marked this pull request as draft July 26, 2026 12:08
@pjh4993 pjh4993 changed the title Drop removed splits from the dataset card when a push replaces the split set Fix DatasetDict.push_to_hub leaving removed splits in the dataset card Jul 26, 2026
@pjh4993
pjh4993 marked this pull request as ready for review July 26, 2026 13:42
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@lhoestq lhoestq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm !

@lhoestq
lhoestq merged commit 6747b87 into huggingface:main Jul 28, 2026
7 of 14 checks passed
Elsword016 pushed a commit to Elsword016/datasets that referenced this pull request Aug 6, 2026
huggingface#8367)

Drop removed splits from the dataset card when a push replaces the split set

DatasetDict.push_to_hub deletes the shards of splits that are no longer in
the dict, but _get_updated_dataset_card only applied remove_other_splits to
the dataset_info block. The configs.data_files patterns were still seeded
from the existing card and splits were only ever added, so a removed split
kept its pattern with no files behind it, making the dataset unloadable:

    ValueError: Couldn't infer the same data file format for all splits.
    Got {'train': ('parquet', {}), 'test': (None, {})}

Skip the seeding when remove_other_splits is set so the patterns describe
only the splits this push wrote. Dataset.push_to_hub passes
remove_other_splits=False and keeps its additive behaviour.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants