keras-team/keras · error · ValueError

The `salt` argument for `IndexLookup` can only be a tuple of

Error message

The `salt` argument for `IndexLookup` can only be a tuple of 2 integers, or a single integer. Received: salt={salt}.

What it means

The `salt` argument accepts either a single integer (used for both FarmHash salt values) or a tuple/list of exactly two integers. Any other type or length cannot map onto FarmHash's salt pair and is rejected.

Source

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

            caller_name=self.__class__.__name__,
            arg_name="oov_method",
        )

        if salt is not None:
            if (
                tf.as_dtype(vocabulary_dtype).is_integer
                and oov_method != "farmhash"
            ):
                raise ValueError(
                    "`salt` can only be used when `oov_method='farmhash'`. "
                    f"Received: oov_method={oov_method}"
                )
            if isinstance(salt, (tuple, list)) and len(salt) == 2:
                salt = list(salt)
            elif isinstance(salt, int):
                salt = [salt, salt]
            else:
                raise ValueError(
                    "The `salt` argument for `IndexLookup` can only be a tuple "
                    "of 2 integers, or a single integer. "
                    f"Received: salt={salt}."
                )

        # Support deprecated names for output_modes.
        if output_mode == "binary":
            output_mode = "multi_hot"
        if output_mode == "tf-idf":
            output_mode = "tf_idf"
        argument_validation.validate_string_arg(
            output_mode,
            allowable_strings=(
                "int",
                "one_hot",
                "multi_hot",
                "count",
                "tf_idf",

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Pass an int: `salt=42` (applied to both salt slots).
  2. Or a 2-element tuple/list of ints: `salt=(42, 43)`.
  3. Coerce config values before use: `salt=int(cfg['seed'])`.

Example fix

# before
layer = IndexLookup(salt=(42, 43, 44), oov_method='farmhash')

# after
layer = IndexLookup(salt=(42, 43), oov_method='farmhash')
Defensive patterns

Strategy: type-guard

Validate before calling

if salt is not None:
    assert isinstance(salt, int) or (isinstance(salt, (tuple, list)) and len(salt) == 2 and all(isinstance(x, int) for x in salt)), 'bad salt: %r' % salt

Type guard

def is_valid_salt(v) -> bool:
    if isinstance(v, bool):
        return False
    if isinstance(v, int):
        return True
    return isinstance(v, (tuple, list)) and len(v) == 2 and all(isinstance(x, int) and not isinstance(x, bool) for x in v)

Prevention

When it happens

Trigger: `salt='seed'`, `salt=[1, 2, 3]`, `salt=(1, 'a')`, or a numpy scalar / string from a config file.

Common situations: Passing seeds loaded from YAML/JSON config as strings, or reusing a 3-element seed tuple from another hashing library.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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