keras-team/keras · error · TypeError

If class_mode="{}", y_col="{}" column values must be strings

Error message

If class_mode="{}", y_col="{}" column values must be strings.

What it means

For class_mode='binary' or 'sparse', the y_col column values must all be strings because labels are mapped through class indices derived from string classes.

Source

Thrown at keras/src/legacy/preprocessing/image.py:818

                )
            )
        # check that y_col has several column names if class_mode is
        # multi_output
        if (self.class_mode == "multi_output") and not isinstance(y_col, list):
            raise TypeError(
                'If class_mode="{}", y_col must be a list. Received {}.'.format(
                    self.class_mode, type(y_col).__name__
                )
            )
        # check that filenames/filepaths column values are all strings
        if not all(df[x_col].apply(lambda x: isinstance(x, str))):
            raise TypeError(
                f"All values in column x_col={x_col} must be strings."
            )
        # check labels are string if class_mode is binary or sparse
        if self.class_mode in {"binary", "sparse"}:
            if not all(df[y_col].apply(lambda x: isinstance(x, str))):
                raise TypeError(
                    'If class_mode="{}", y_col="{}" column '
                    "values must be strings.".format(self.class_mode, y_col)
                )
        # check that if binary there are only 2 different classes
        if self.class_mode == "binary":
            if classes:
                classes = set(classes)
                if len(classes) != 2:
                    raise ValueError(
                        'If class_mode="binary" there must be 2 '
                        "classes. {} class/es were given.".format(len(classes))
                    )
            elif df[y_col].nunique() != 2:
                raise ValueError(
                    'If class_mode="binary" there must be 2 classes. '
                    "Found {} classes.".format(df[y_col].nunique())
                )
        # check values are string, list or tuple if class_mode is categorical

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Cast labels to strings: df[y_col] = df[y_col].astype(str)
  2. Or use class_mode='categorical'/'raw' with numeric labels
  3. Keep exactly 2 distinct string classes for binary

Example fix

// before
df['label'] = df['label']  # 0/1 ints, class_mode='binary'
// after
df['label'] = df['label'].astype(str)  # '0'/'1'
Defensive patterns

Strategy: validation

Validate before calling

assert df[y_col].map(lambda v: isinstance(v, str)).all()

Type guard

def labels_are_str(col): return col.map(lambda v: isinstance(v, str)).all()

Try / catch

try: flow_from_dataframe(..., class_mode='binary')
except TypeError as e: if 'must be strings' in str(e): df[y_col] = df[y_col].astype(str)

Prevention

When it happens

Trigger: flow_from_dataframe(class_mode='binary'/'sparse') with numeric labels (0/1 ints) in y_col.

Common situations: CSV with integer labels; assuming numeric labels are accepted like in flow().

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/44f2b7738cc0fa0a. Report an issue: GitHub.