{"record":{"id":"724a1e78ca564f99","repo":"keras-team/keras","slug":"cannot-concatenate-features-because-feature-name","errorCode":null,"errorMessage":"Cannot concatenate features because feature '{name}' has not been encoded (it has dtype {dtype}). Consider using `output_mode='dict'`.","messagePattern":"Cannot concatenate features because feature '(.+?)' has not been encoded \\(it has dtype (.+?)\\)\\. Consider using `output_mode='dict'`\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/preprocessing/feature_space.py","lineNumber":721,"sourceCode":"                else:\n                    raise ValueError(\n                        f\"Feature '{name}' has `output_mode='one_hot'`. \"\n                        \"However it isn't a standard feature and the \"\n                        \"dimensionality of its output space is not known, \"\n                        \"thus it cannot be one-hot encoded. \"\n                        \"Try using `output_mode='int'`.\"\n                    )\n                if cardinality is not None:\n                    encoder = layers.CategoryEncoding(\n                        num_tokens=cardinality, output_mode=\"multi_hot\"\n                    )\n                    self.one_hot_encoders[name] = encoder\n                    feature = encoder(feature)\n\n            if self.output_mode == \"concat\":\n                dtype = feature.dtype\n                if dtype.startswith(\"int\") or dtype == \"string\":\n                    raise ValueError(\n                        f\"Cannot concatenate features because feature '{name}' \"\n                        f\"has not been encoded (it has dtype {dtype}). \"\n                        \"Consider using `output_mode='dict'`.\"\n                    )\n                features_to_concat.append(feature)\n            else:\n                output_dict[name] = feature\n\n        if self.output_mode == \"concat\":\n            self.concat = TFDConcat(axis=-1)\n            return self.concat(features_to_concat)\n        else:\n            return output_dict\n\n    def _check_if_adapted(self):\n        if not self._is_adapted:\n            if not self._list_adaptable_preprocessors():\n                self._is_adapted = True","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/preprocessing/feature_space.py#L703-L739","documentation":"In output_mode='concat', FeatureSpace concatenates all features into one float tensor. If a feature still has an integer or string dtype it was never encoded (e.g. a crossing with output_mode='int' left raw), and concatenation is impossible. Set an encoding output mode or use 'dict' output.","triggerScenarios":"FeatureSpace(output_mode='concat') while a feature or crossing produces raw int/string output, typically crossing_output_mode='int' left at default with concat output.","commonSituations":"Leaving crossing_output_mode='int' while FeatureSpace output_mode='concat'; forgetting to set output_mode on the FeatureSpace so unencoded integer lookups flow into concat.","solutions":["Set crossing_output_mode='one_hot' (or FeatureSpace output_mode='one_hot') so cross features get encoded before concat","Use output_mode='dict' if you want raw per-feature outputs","Verify each feature's spec produces encoded (float) output when concatenating"],"exampleFix":"// before\nfs = FeatureSpace(..., output_mode=\"concat\")  # crossing_output_mode='int' default\n// after\nfs = FeatureSpace(..., output_mode=\"concat\", crossing_output_mode=\"one_hot\")\n# or use output_mode=\"dict\" for raw outputs","handlingStrategy":"validation","validationCode":"p = fs.preprocessors.get(name) or fs.crossers.get(name)\nout = p(sample_batch)\nassert not (str(out.dtype).startswith(\"int\") or str(out.dtype) == \"string\"), f\"{name} unencoded for concat\"","typeGuard":"def is_encoded(name, feature_space):\n    return not (name in feature_space.crossers and getattr(feature_space, \"crossing_output_mode\", \"int\") == \"int\" and feature_space.output_mode == \"concat\")","tryCatchPattern":"catch ValueError from get_encoded_features()/__call__, then either set an encoding output_mode or switch FeatureSpace to output_mode='dict'","preventionTips":["Set crossing/output_mode='int' or 'one_hot' so every feature is encoded before concat","Use output_mode='dict' when you want raw (unencoded) feature outputs"],"tags":["keras","feature-space","concat","encoding"],"backgroundTag":"invalid-configuration","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}