{"record":{"id":"b0639686187b0137","repo":"keras-team/keras","slug":"expected-rebatched-data-to-have-batch-size-1-rece","errorCode":null,"errorMessage":"Expected rebatched data to have batch size 1. Received: shape={merged_data.shape}","messagePattern":"Expected rebatched data to have batch size 1\\. Received: shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/preprocessing/feature_space.py","lineNumber":798,"sourceCode":"            # This scope is to make sure that inner DataLayers\n            # will not convert outputs back to backend-native --\n            # they should be TF tensors throughout\n            preprocessed_data = self._preprocess_features(data)\n            preprocessed_data = tree.map_structure(\n                lambda x: self._convert_input(x), preprocessed_data\n            )\n\n            crossed_data = self._cross_features(preprocessed_data)\n            crossed_data = tree.map_structure(\n                lambda x: self._convert_input(x), crossed_data\n            )\n\n            merged_data = self._merge_features(preprocessed_data, crossed_data)\n\n        if rebatched:\n            if self.output_mode == \"concat\":\n                if merged_data.shape[0] != 1:\n                    raise ValueError(\n                        \"Expected rebatched data to have batch size 1. \"\n                        f\"Received: shape={merged_data.shape}\"\n                    )\n                if (\n                    backend.backend() != \"tensorflow\"\n                    and not backend_utils.in_tf_graph()\n                ):\n                    merged_data = np.array(merged_data)\n                merged_data = tf.squeeze(merged_data, axis=0)\n            else:\n                for name, x in merged_data.items():\n                    if len(x.shape) == 2 and x.shape[0] == 1:\n                        merged_data[name] = tf.squeeze(x, axis=0)\n\n        if (\n            backend.backend() != \"tensorflow\"\n            and not backend_utils.in_tf_graph()\n        ):","sourceCodeStart":780,"sourceCodeEnd":816,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/preprocessing/feature_space.py#L780-L816","documentation":"When FeatureSpace is used with rebatched=True (e.g. wired as a keras Input via dict_inputs), the internal merge must yield exactly one row so downstream graph construction is unambiguous with output_mode='concat'. A leading batch dimension other than 1 breaks the Functional-model contract.","triggerScenarios":"Passing a batched dataset element (batch_size > 1) or a multi-row dict to a FeatureSpace used as a keras Input, with output_mode='concat'.","commonSituations":"Using FeatureSpace directly as a keras Input in a Functional model; passing a batched dataset element (batch_size > 1) to that input; rebatching the data with more than one row before the call.","solutions":["Pass data with batch size 1 (a single sample dict) when calling the FeatureSpace directly as an Input","Prefer fs.get_encoded_features() as the model input and feed raw dicts through tf.data instead of calling fs() manually","Check merged_data.shape[0]; unbatch your dataset before the call"],"exampleFix":"// before\ninputs = fs.get_encoded_features()  # ok\nmodel = keras.Model(inputs, x)\nout = model(fs(raw_batched_dict))  # batch > 1 -> error path\n// after\nout = model(fs(raw_single_row_dict))  # one row at a time\n# or build: encoded = fs.get_encoded_features(); model = keras.Model(encoded, x)","handlingStrategy":"validation","validationCode":"if isinstance(data, tf.data.Dataset):\n    data = data.unbatch().take(1)\nassert all(int(v.shape[0]) == 1 for v in batch.values())","typeGuard":"def is_single_row(d):\n    return all(len(v.shape) == 0 or int(v.shape[0]) == 1 for v in d.values())","tryCatchPattern":"catch ValueError and pass data with batch size 1 (or the unbatched raw dict for Input usage) instead of a multi-row batch","preventionTips":["When using FeatureSpace as a keras Input, pass the raw unbatched dict and let the layer batch internally","Do not pre-batch data passed directly to a FeatureSpace Input"],"tags":["keras","feature-space","batch-size","shape"],"backgroundTag":"shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}