keras-team/keras · error · ValueError

Found reserved OOV token at unexpected location in `vocabula

Error message

Found reserved OOV token at unexpected location in `vocabulary`. Note that passed `vocabulary` does not need to include the OOV and mask tokens. Either remove all mask and OOV tokens, or include them only at the start of the vocabulary in precisely this order: {special_tokens}. Received: oov_token={self.oov_token} at vocabulary index {oov_index}

What it means

The OOV-token counterpart of the mask-token check, applied on inverted (index-to-token) layers: if the oov_token appears in the passed vocabulary outside its reserved head slot, the reverse mapping would be ambiguous.

Source

Thrown at keras/src/layers/preprocessing/index_lookup.py:538

            mask_index = np.argwhere(vocabulary == self.mask_token)[-1]
            raise ValueError(
                "Found reserved mask token at unexpected location in "
                "`vocabulary`. Note that passed `vocabulary` does not need to "
                "include the OOV and mask tokens. Either remove all mask and "
                "OOV tokens, or include them only at the start of the "
                f"vocabulary in precisely this order: {special_tokens}. "
                f"Received: mask_token={self.mask_token} at "
                f"vocabulary index {mask_index}"
            )
        # Only error out for oov_token when invert=True. When invert=False,
        # oov_token is unused during lookup.
        if (
            self.oov_token is not None
            and self.invert
            and self.oov_token in tokens
        ):
            oov_index = np.argwhere(vocabulary == self.oov_token)[-1]
            raise ValueError(
                "Found reserved OOV token at unexpected location in "
                "`vocabulary`. Note that passed `vocabulary` does not need to "
                "include the OOV and mask tokens. Either remove all mask and "
                "OOV tokens, or include them only at the start of the "
                f"vocabulary in precisely this order: {special_tokens}. "
                f"Received: oov_token={self.oov_token} at "
                f"vocabulary index {oov_index}"
            )

        new_vocab_size = token_start + len(tokens)
        if self.max_tokens is not None and (new_vocab_size > self.max_tokens):
            raise ValueError(
                "Attempted to set a vocabulary larger than the maximum vocab "
                f"size. Received vocabulary size is {new_vocab_size}; "
                f"`max_tokens` is {self.max_tokens}."
            )
        self.lookup_table = self._lookup_table_from_tokens(tokens)
        self._record_vocabulary_size()

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Strip the oov token from the vocabulary before passing it.
  2. Or place it exactly at the reserved head position per the documented special-token order.
  3. Ensure encoder and decoder layers use consistent oov_token and num_oov_indices settings.

Example fix

# before
inv_layer.set_vocabulary(vocab)  # vocab includes '[UNK]'

# after
tokens = [t for t in vocab if t != '[UNK]']
inv_layer.set_vocabulary(tokens)
Defensive patterns

Strategy: validation

Validate before calling

vocab = [t for t in vocab if t != '[UNK]']
inv_layer.set_vocabulary(vocab)

Type guard

def free_of_oov(vocab, oov_token) -> bool:
    return oov_token not in vocab

Prevention

When it happens

Trigger: `layer.set_vocabulary(vocab)` on a layer with `invert=True` where vocab contains '[UNK]' at any position other than the reserved slot.

Common situations: Building a decoder lookup from a vocabulary file that already includes the '[UNK]' token.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/b56000a3076f2222. Report an issue: GitHub.