Skip to content

Fix crash with Lhotse train data and float limit_train_batches - #16131

Open
VaggelisGian wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
VaggelisGian:fix-lhotse-len-limit-train-batches
Open

Fix crash with Lhotse train data and float limit_train_batches#16131
VaggelisGian wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
VaggelisGian:fix-lhotse-len-limit-train-batches

Conversation

@VaggelisGian

Copy link
Copy Markdown

Important

The Update branch button must only be pressed in very rare occassions.
An outdated branch is never blocking the merge of a PR.
Please reach out to the automation team before pressing that button.

What does this PR do ?

Fixes #16004: training crashes with TypeError: object of type 'LhotseSpeechToTextBpeDatasetWithPromptIndex' has no len() whenever limit_train_batches is a float (including the Lightning default of 1.0) while the train data comes from Lhotse.

Collection: ASR

Changelog

  • In EncDecHybridRNNTCTCBPEModel and the prompt-based RNNT model, the limit_train_batches conversion now enters only when the dataloader's dataset is an IterableDataset that also defines __len__, matching the guard pattern already used by the base class for the other ASR models.
  • NeMo tarred datasets still qualify and keep the conversion; Lhotse map-style datasets and IterableDatasetWrapper skip it, so Lightning keeps treating a float value as a fraction of one epoch.
  • Adds a regression test that reproduces the reported TypeError before the fix and passes after it.

Root cause: both models guarded the conversion on the is_tarred config key and then called len() on the built dataset. With use_lhotse=true the dataset is map-style without __len__, so any float limit_train_batches raised the crash from the linked issue.

Usage

No configuration change is required. With model.train_ds.use_lhotse=true, any float trainer.limit_train_batches now trains normally instead of crashing:

trainer:
  limit_train_batches: 0.5   # or the default 1.0
model:
  train_ds:
    use_lhotse: true

GitHub Actions CI

The Jenkins CI system has been replaced by GitHub Actions self-hosted runners.

Trusted PRs run automatically through copy-pr-bot. For an untrusted PR, a maintainer can trigger CI by commenting
/ok to test <head-sha>; repeat this after a new push if the PR remains untrusted.

Before your PR is "Ready for review"

Pre checks:

  • Make sure you read and followed Contributor guidelines
  • Did you write any new necessary tests? Yes: regression test in tests/collections/asr/test_asr_rnnt_encoder_model_bpe_prompt.py, fails before the fix (TypeError ... has no len()) and passes after.
  • Did you add or update any necessary documentation? No documentation change needed: pure bug fix, no public API, config key, CLI behavior, or user workflow changed.
  • Does the PR affect components that are optional to install? (Ex: Numba, Pynini, Apex etc) No, no optional dependency is touched, so no new import guards are needed.
    • Reviewer: Does the PR have correct import guards for all optional libraries? N/A.

PR Type:

  • New Feature
  • Bugfix
  • Documentation

Who can review?

Anyone in the community is free to review the PR once the checks have passed.
Contributor guidelines contains specific people who can review PRs to various areas.

Additional Information

Exact checks run locally (Python 3.12.6, torch 2.11.0+cu128):

python -m pytest tests/collections/asr/test_asr_rnnt_encoder_model_bpe_prompt.py -x -q -m "not pleasefixme"
  -> 13 passed (57s), including the new regression test
python -m pytest tests/collections/asr/test_asr_hybrid_rnnt_ctc_model_bpe_prompt.py -q -m "not pleasefixme"
  -> 15 passed (105s)
python -m black --check --diff <changed files>      -> clean
python -m isort --check-only --diff <changed files> -> clean
python -m flake8 <changed files>                    -> clean
git diff --check                                    -> clean

Intentionally skipped: full ASR suite (blast radius of this change is two setup methods plus their base-class pattern), docs build (uv unavailable on this machine), pre-commit binary absent locally; black/isort/flake8 were run directly against the same pinned configs instead.

The prompt-based RNNT and hybrid RNNT-CTC models guarded their
limit_train_batches conversion on the is_tarred config key and then
called len() on the built dataset. With use_lhotse=true the dataset
is a map-style torch Dataset without __len__, so any float
limit_train_batches (including the Lightning default 1.0) raised:
TypeError: object of type 'LhotseSpeechToTextBpeDatasetWithPromptIndex'
has no len()

Align the guard with the base-class pattern used by the other ASR
models: enter only when the dataloader holds an IterableDataset that
also defines __len__. NeMo tarred datasets qualify and keep the
conversion; Lhotse map-style datasets and IterableDatasetWrapper do
not, so the conversion is skipped and Lightning keeps treating 1.0 as
a full epoch.

Fixes NVIDIA-NeMo#16004.

Test Plan:
  python -m pytest tests/collections/asr/test_asr_rnnt_encoder_model_bpe_prompt.py -x -q -m "not pleasefixme"
    13 passed, including the new regression test that reproduces the
    reported TypeError before the fix
  python -m pytest tests/collections/asr/test_asr_hybrid_rnnt_ctc_model_bpe_prompt.py -q -m "not pleasefixme"
    15 passed
  black --check, isort --check-only, flake8 on changed files: clean

Signed-off-by: Vaggelis <baggelis100@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the ASR label Aug 25, 2026
@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-maintainers Waiting on maintainers to respond label Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ASR community-request waiting-on-maintainers Waiting on maintainers to respond

2 participants