{"record":{"id":"6de1fb52879de6b9","repo":"keras-team/keras","slug":"if-class-mode-binary-there-must-be-2-classes-fo","errorCode":null,"errorMessage":"If class_mode=\"binary\" there must be 2 classes. Found {} classes.","messagePattern":"If class_mode=\"binary\" there must be 2 classes\\. Found (.+?) classes\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/preprocessing/image.py","lineNumber":832,"sourceCode":"            )\n        # check labels are string if class_mode is binary or sparse\n        if self.class_mode in {\"binary\", \"sparse\"}:\n            if not all(df[y_col].apply(lambda x: isinstance(x, str))):\n                raise TypeError(\n                    'If class_mode=\"{}\", y_col=\"{}\" column '\n                    \"values must be strings.\".format(self.class_mode, y_col)\n                )\n        # check that if binary there are only 2 different classes\n        if self.class_mode == \"binary\":\n            if classes:\n                classes = set(classes)\n                if len(classes) != 2:\n                    raise ValueError(\n                        'If class_mode=\"binary\" there must be 2 '\n                        \"classes. {} class/es were given.\".format(len(classes))\n                    )\n            elif df[y_col].nunique() != 2:\n                raise ValueError(\n                    'If class_mode=\"binary\" there must be 2 classes. '\n                    \"Found {} classes.\".format(df[y_col].nunique())\n                )\n        # check values are string, list or tuple if class_mode is categorical\n        if self.class_mode == \"categorical\":\n            types = (str, list, tuple)\n            if not all(df[y_col].apply(lambda x: isinstance(x, types))):\n                raise TypeError(\n                    'If class_mode=\"{}\", y_col=\"{}\" column '\n                    \"values must be type string, list or tuple.\".format(\n                        self.class_mode, y_col\n                    )\n                )\n        # raise warning if classes are given but will be unused\n        if classes and self.class_mode in {\n            \"input\",\n            \"multi_output\",\n            \"raw\",","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/preprocessing/image.py#L814-L850","documentation":"With class_mode='binary' and no classes argument, the y_col column must contain exactly 2 unique values. This variant reports the count found in the DataFrame.","triggerScenarios":"flow_from_dataframe(class_mode='binary') where df[y_col].nunique() != 2 (e.g. 3 classes, or 1 after filtering).","commonSituations":"Filtering the DataFrame leaves 1 class; exploratory dataset actually has 3+ labels.","solutions":["Filter rows so exactly 2 labels remain","Pass classes=[pos,neg] explicitly to pin the two labels","Switch to class_mode='categorical' for multi-class"],"exampleFix":"// before\ngen.flow_from_dataframe(df, x_col='f', y_col='label', class_mode='binary')  # 3 labels\n// after\ndf = df[df.label.isin(['cat','dog'])]\ngen.flow_from_dataframe(df, x_col='f', y_col='label', class_mode='binary')\n","handlingStrategy":"validation","validationCode":"assert df[y_col].nunique() == 2","typeGuard":null,"tryCatchPattern":"try: flow_from_dataframe(..., class_mode='binary')\nexcept ValueError as e: if 'Found' in str(e) and 'classes' in str(e): raise SystemExit('fix labels')","preventionTips":["Print df[y_col].value_counts() before constructing the iterator"],"tags":["keras","binary-classification","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}