๐Ÿ”

Whisper Repeating Words Loop Bug: Real Fixes

When the decoder gets stuck and won't emit EOS

TL;DR: The Whisper repeating-words loop is a known decoding failure. The autoregressive decoder loses confidence in emitting its end-of-sequence (EOS) token, the next-token probabilities collapse onto a short phrase, and the model prints that phrase over and over until it hits your max_length cap. OpenAI's own reference repo documents the mitigations: repetition_penalty, temperature fallback, condition_on_previous_text=False, compression_ratio_threshold, and no_speech_threshold. openai/whisper, WhisperKit, faster-whisper, and whisper.cpp all expose variants of these. large-v3 and large-v3-turbo do it less often than older checkpoints, but no model is immune. If you're using MetaWhisp, the WhisperKit engine we ship already applies the safer defaults, so you'll see this far less than a hand-rolled pipeline.
Whisper decoder loop schematic showing the repeating words bug where EOS token fails to be emitted

What does the Whisper repeating-words loop bug actually look like?

You transcribe a 20-minute meeting. The first 14 minutes look great. Then, somewhere around a pause or a question, the transcript starts printing the same short phrase over and over: "Yeah, yeah, yeah, yeah, yeahโ€ฆ", or "Thank you. Thank you. Thank you. Thank you.", or sometimes a longer fragment like "So that's why I think we should, so that's why I think we should, so that's why I think we shouldโ€ฆ". The transcript doesn't stop. It runs until the decoder hits its hard length limit (default 448 tokens in the OpenAI pipeline) and then you get a wall of repetition where your real content used to be. It isn't a typo. It isn't a transcription service glitching out. It's the model itself โ€” running normally, just stuck. This has been reported on the openai/whisper issue tracker since the model went public in late 2022, with new reports still landing on WhisperKit, faster-whisper, and whisper.cpp for the newer checkpoints. It's a widely-reported Whisper failure mode, and it has a real cause. Not a quirk, not bad luck โ€” a known weakness in how the decoder decides when to stop.
Pro tip: Before you blame your microphone or your audio format, scroll your transcript and look for any run of three or more identical short phrases back to back. If you see it, you're in loop-bug territory. The fix lives in the decoder, not in your recording setup.

Why does the Whisper decoder get stuck repeating the same phrase?

The original Whisper paper ("Robust Speech Recognition via Large-Scale Weak Supervision", Radford et al., 2022) describes an encoder-decoder Transformer. The encoder turns audio into a representation. The decoder generates text tokens one at a time, conditioned on both the encoder output and the tokens it has already produced. That second part matters. Because the decoder is autoregressive โ€” every token it generates becomes input to the next step โ€” small errors compound. If the model's probability for the EOS token ("I'm done, end the sequence") drops even slightly below the probability for, say, the word "Yeah", the decoder picks "Yeah". Now the next step has "Yeah" in its context. Without a repetition_penalty, the model often finds "Yeah" even more probable, because the encoder's attention heads now have a familiar anchor to look at. What you see on screen is the loop. What the model sees internally is a feedback where the EOS probability keeps getting outvoted by the repeated phrase, especially when: - The audio has a long pause, breath, or low-energy silence. - The chunk being decoded doesn't clearly contain a sentence boundary. - The previous chunk ended ambiguously (so the conditioning context carries doubt forward). This kind of failure is sometimes called repetition hallucination or loop hallucination. It's not unique to Whisper โ€” neural sequence models in general can fall into it โ€” but Whisper's decoder width and the way it carries previous-text context make it unusually visible in long-form transcription.
Token probability comparison showing repetition penalty effect on Whisper decoder output
What causes Whisper to repeat words in a loop? The autoregressive decoder loses confidence in the end-of-sequence (EOS) token. Without a repetition penalty, each repetition of the same phrase raises its probability further, so the model keeps emitting it instead of stopping. Long pauses, ambiguous chunk boundaries, and condition_on_previous_text=True (the OpenAI default) all make it worse. The original Whisper paper describes the architecture; the failure mode was discovered post-release and is documented across openai/whisper issues. It's a token-sampling pathology, not a bug in the weights themselves.

What are the OpenAI-recommended decoding parameters that fix most cases?

The reference transcribe() function in the openai/whisper repo exposes a handful of decoding knobs. Most users never touch them. For the loop bug, these are the ones that matter: - condition_on_previous_text=False. The single biggest lever. By default, Whisper feeds the previous chunk's transcript back into the decoder as context. If the previous chunk ended in an awkward place, that awkwardness carries forward and primes the loop. Setting this to False makes each chunk independent. It costs you a tiny bit of cross-sentence coherence; it saves you from most loops. - repetition_penalty (a float, typically 1.1 to 1.3). Penalizes tokens that have already appeared. Values above 1.0 suppress repetition; values too high (>1.5) garble the output. This is the parameter that directly targets the feedback loop. - temperature with fallback (a tuple like (0.0, 0.2, 0.4, 0.6, 0.8, 1.0)). When the decoder's average log-probability drops below logprob_threshold, the pipeline falls back to a higher temperature. This gives the model a chance to escape a low-confidence attractor state โ€” exactly the loop situation. - compression_ratio_threshold (default 2.4). If the gzip compression ratio of the output so far exceeds this, the pipeline gives up and returns nothing. A loop has a very low compression ratio (highly repetitive = compresses wellโ€ฆ actually highly repetitive = compresses very well, so this catches the opposite case of garbled output). It's still useful as a sanity check. - no_speech_threshold (default 0.6) and logprob_threshold (default -1.0). These let the pipeline refuse to output a transcript when confidence is too low. They don't fix a loop directly; they let you detect when the model is guessing. None of these are toggled on by default for the loop case. You have to set them.
ParameterDefault in openai/whisperLoop-bug fix?
condition_on_previous_text=FalseTrueYes โ€” biggest single win
repetition_penalty=1.1โ€“1.3not setYes โ€” directly targets feedback
temperature fallback tuple0 (greedy)Yes โ€” lets decoder escape attractors
logprob_threshold-1.0Indirect โ€” detects low confidence
no_speech_threshold0.6Indirect โ€” refuses to transcribe silence
compression_ratio_threshold2.4Indirect โ€” sanity check on output

Does Whisper large-v3-turbo still have the repetition bug?

Yes โ€” but less often. OpenAI's checkpoint history matters here. Whisper large-v2 (the second-generation large model) was the one most users started with. large-v3 was a retrain on more data, including broader multilingual coverage. large-v3-turbo uses the same v3 weights but with the decoder layers pruned from 32 down to 4 for speed.
ModelDecoder layersLoop bug reported?
large-v232Yes โ€” frequent on long-form, pauses, music bleed
large-v332Yes โ€” less often, still reported on the issue tracker
large-v3-turbo4Yes โ€” less often, inherits v3's failure modes
Pruning decoder layers doesn't fix the EOS-stuck pathology. The same sampling loop exists; it just runs with fewer parameters per step. The community-reported improvement in v3 is more likely due to better training data and tokenizer than to anything architectural. The Hugging Face model cards for openai/whisper-large-v3 and openai/whisper-large-v3-turbo describe the size and language changes; they don't promise anything about decoding stability. The "fewer loops in v3" claim comes from accumulated issue-tracker reports, not from a benchmark OpenAI published. Treat it as directionally true, not as a guarantee. For more on what v3-turbo is and what it isn't, see our breakdown of Whisper large-v3-turbo.
What is the best repetition penalty value for Whisper? For openai/whisper the commonly-recommended range is 1.1 to 1.3. Start at 1.1. If the loop persists, try 1.2. Going past 1.5 starts to garble the output โ€” the penalty hits legitimate repeated words like "I", "the", and "that". Combine it with condition_on_previous_text=False for the best result. WhisperKit, faster-whisper, and whisper.cpp each expose their own version of this parameter; the same range applies.

How does WhisperKit handle the bug compared to faster-whisper and whisper.cpp?

The four most common ways to run Whisper locally each handle the loop bug a bit differently, because they each picked slightly different default decoding strategies: - argmax/WhisperKit (the engine MetaWhisp ships) is optimized for Apple Silicon and the Neural Engine. Its decoding options expose the standard set โ€” repetition penalty, condition-on-previous-text, temperature โ€” and its defaults commonly favor shorter inputs, which means it rarely sees the long-form context that primes the loop. When you ask it to transcribe long dictation, the defaults are conservative enough that the bug surfaces far less than the reference OpenAI pipeline. - SYSTRAN/faster-whisper is a CTranslate2-backed reimplementation. It has its own repetition-penalty handling and commonly uses temperature fallback more aggressively. Users running it on long-form often report fewer loops than the reference Python pipeline, but the bug isn't eliminated. - ggerganov/whisper.cpp is the C++ port. It implements a separate set of decoding parameters and exposes repetition_penalty, temperature, and no_context (which is the analog of condition_on_previous_text=False). It's commonly regarded as the most configurable of the three. - Cloud APIs (OpenAI's hosted Whisper endpoint, AssemblyAI, Deepgram) abstract most of this away. You usually don't get to set repetition penalty directly. The provider either has the safer defaults on or it doesn't, and your only lever is chunking your audio yourself before sending. The honest summary: every local engine ships with knobs that fix the loop bug, but none of them turn the knobs on for you by default. The fix is configuration, not magic.
Whisper model versions diagram comparing decoder layer counts and repetition bug status

How do you recover a transcript when the loop bug strikes mid-recording?

You don't recover the lost words. The model never produced them โ€” it produced a loop instead. What you can do is recover everything up to the loop and re-transcribe the rest. The practical workflow: 1. Find the loop boundary. Scroll your transcript. The loop is usually obvious: three or more identical short phrases back to back. Mark the last clean sentence before it starts. 2. Split the audio. Cut the source recording at the loop boundary. Most editors can do this in seconds. 3. Re-transcribe the post-loop chunk independently. Run Whisper on just that chunk, with condition_on_previous_text=False and a repetition penalty. Don't feed it the partial transcript as context โ€” that's how the loop got in in the first place. 4. Stitch the results manually. Paste the clean first half and the new second half together. The seam will be visible; the content will be correct. This is the workflow I use when I'm dictating long pieces and hit the bug. It costs you maybe 60 seconds of editing per occurrence. It's not elegant, but it works. If you want to avoid the loop in the first place, the cleaner path is to transcribe in shorter segments โ€” say, two to three minutes at a time โ€” rather than feeding the model a single 30-minute file. The OpenAI repo's long-form transcription script does this chunking internally, but only when you tell it to.
Why does the bug get worse on long audio? Long audio means long context for the decoder. Two things compound. First, condition_on_previous_text=True (the OpenAI default) feeds every previous chunk's transcript back in; any ambiguity at a chunk boundary carries forward and biases the next chunk's decoding. Second, the model has more opportunities to hit a low-confidence attractor state on long audio โ€” pauses, breaths, cross-talk, topic shifts. The fix is shorter, independent chunks. WhisperKit and the other engines have the same behavior; none of them magically detect the attractor and break out of it.

Is there a way to detect a loop automatically?

You can write one in about ten lines of Python. After each generated segment, check: - Does the last N tokens repeat the same phrase more than M times? - Is the segment's length close to the model's max_length cap (448 tokens in the reference pipeline)? - Is the gzip compression ratio suspiciously low (lots of repetition compresses very well)? If any of those trigger, discard the segment and either lower the temperature, raise the repetition penalty, or split the chunk. None of the four major engines ship this loop detector out of the box โ€” they each rely on the threshold parameters above to bail out at decode time, which is coarser than detecting mid-decode. For most users, the manual workflow is fast enough. The detector is worth writing if you're processing hours of audio per day.
Long audio chunking workflow for avoiding Whisper repetition loop bug on long recordings

When the bug isn't really the bug: the checklist before you start tuning

If you're hitting the loop on every single recording โ€” not just long ones โ€” work through this before touching any decoding parameters: - Audio is actually recording. Sounds dumb, but a muted mic produces a flat-line waveform that the model hallucinates on. Always plot the waveform. - Sample rate is 16 kHz mono PCM (or close to it). Whisper was trained on 16 kHz mono. Anything else gets resampled, and a bad resample can introduce artifacts that look like the loop bug but aren't. - You're not hitting the model's max_length cap. A transcript that cuts off cleanly at exactly 448 tokens isn't a loop โ€” it's a length cap. Shorten your chunks. - The audio isn't mostly silence. Silence with rare words primes the model to repeat whatever few words it has. Use voice activity detection upstream, or use no_speech_threshold. - You're not accidentally in a chat-style session with prior turns. Long-context chat sessions with Whisper in the loop can carry stale conditioning. Close and reopen. If all of those check out and you still see the loop, you're in the actual bug and the parameter fixes above will help. If you've ruled them out and the symptom persists, the issue may be macOS-level โ€” Apple's own Dictation has its own quirks. We covered the most common ones in Mac Dictation Not Working.
How do I recover a transcript that got stuck in a loop? You can't recover the lost words โ€” the model never generated them, it generated a loop. What you can do is recover everything up to the loop: find the loop boundary, cut the source audio there, re-transcribe the post-loop chunk with condition_on_previous_text=False and a repetition penalty in the 1.1โ€“1.3 range, then stitch the two halves. For long-form work, the better strategy is to transcribe in two- to three-minute chunks from the start, so a single loop failure costs you a few seconds of editing, not minutes.

How this maps onto MetaWhisp's workflow

I built MetaWhisp because I dictate every day and I didn't want to keep fighting this bug across a dozen recordings. The app uses WhisperKit running large-v3-turbo on the Apple Neural Engine. WhisperKit's defaults are tuned for short utterances, which means the long-form loop is rare in day-to-day use. For longer dictation โ€” say, drafting a blog post like this one โ€” I rely on MetaWhisp's processing modes to clean up after the model. The "Correct" mode applies a structured pass over the transcript, which catches and removes residual repetitions even when the decoder slipped one past the parameter defaults. It does this by sending only the transcript text (never the audio) to your own OpenAI or Cerebras API key โ€” audio stays on the Mac. If you want to see whether the bug bites less under this setup, the free download is the fastest way. There's no account, no cap on local usage, and the model โ€” about 950 MB โ€” runs entirely on your M-series Mac. The local path on the free tier is unlimited. For users whose work involves confidential material โ€” legal, medical, financial โ€” local-only matters for reasons well beyond the loop bug. We wrote about the broader picture in Private Voice to Text on Mac. The short version: nothing leaves the device unless you turn on cloud features yourself.

FAQ

What causes Whisper to repeat words in a loop?

An autoregressive decoder pathology where the model loses confidence in its end-of-sequence (EOS) token. Without a repetition_penalty, each repetition of a phrase raises its probability further, so the model keeps emitting it instead of stopping. Documented across the openai/whisper issue tracker since the original 2022 release; still present in large-v3 and large-v3-turbo, just less often.

Does Whisper large-v3 still have the repetition bug?

Yes โ€” less often than large-v2, but still reported. large-v3-turbo inherits the failure mode because it shares v3's weights (only the decoder layer count is pruned, from 32 to 4, for speed). The improvement in v3 is most likely from better training data and tokenizer, not architecture.

What's the best repetition penalty value for Whisper?

1.1 to 1.3 in openai/whisper. Start at 1.1; go to 1.2 if the loop persists. Above 1.5, the penalty starts garbling legitimate repeated words ("I", "the", "that"). Combine with condition_on_previous_text=False for the best result.

Can I fix the loop bug without retraining?

Yes โ€” decoding-time parameters do most of the work. You do not need to fine-tune or retrain. Set repetition_penalty, set condition_on_previous_text=False, add a temperature fallback tuple, and consider chunking long audio into two- to three-minute segments.

Why does the bug get worse on long audio?

Long audio gives the decoder more context to lose track in. condition_on_previous_text=True (the default) feeds every prior chunk's transcript back in; any ambiguity at a chunk boundary carries forward. Long pauses and cross-talk raise the odds of hitting a low-confidence attractor. Shorter, independent chunks largely solve this.

How do I recover a transcript that got stuck in a loop?

Find the loop boundary, cut the source audio there, re-transcribe the post-loop chunk independently with condition_on_previous_text=False and a repetition penalty, then stitch the two halves. You won't recover the words the model emitted during the loop โ€” but everything before it should be intact.

Is there a way to detect the loop automatically?

You can write a detector in a few lines: watch for any phrase repeated more than N times in a segment, watch for segments close to the max_length cap, watch for suspiciously low gzip compression ratios. None of the major engines ship this detector by default; they rely on threshold parameters to bail out at decode time, which is coarser.

Does the bug happen more in certain languages?

Reports on the issue tracker skew toward English because that's where most long-form transcription happens, but the underlying mechanism โ€” EOS probability collapse โ€” is language-agnostic. Any language with low-resource training data tends to see more of it. Multilingual checkpoints like large-v3 handle high-resource languages better than low-resource ones.

Is the bug the same in WhisperKit, faster-whisper, and whisper.cpp?

Same mechanism, different default tunings. Each engine exposes its own version of repetition_penalty, temperature, and condition-on-previous-text. WhisperKit commonly favors shorter inputs (so the bug is rarer in casual use); faster-whisper commonly uses temperature fallback more aggressively; whisper.cpp is commonly regarded as the most configurable. None of them turn the knobs on for you.


About the author: Andrew Dyuzhov is the CEO and solo founder of MetaWhisp. He's a marketer-turned-builder with ADHD who assembled MetaWhisp on top of open-source Whisper and ships a dictation app he uses daily in Russian and English. He's not an ML researcher; the fixes in this article come from public Whisper documentation and accumulated community testing, not from insider knowledge of OpenAI's training pipeline. Find him on X.

Related reading