{"record":{"id":"446c989907ebce52","repo":"keras-team/keras","slug":"invalid-reduction-key-key-expected-keys-are","errorCode":null,"errorMessage":"Invalid Reduction Key: {key}. Expected keys are \"{cls.all()}\"","messagePattern":"Invalid Reduction Key: (.+?)\\. Expected keys are \"(.+?)\"","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/losses.py","lineNumber":18,"sourceCode":"from keras.src.api_export import keras_export\n\n\n@keras_export(\"keras._legacy.losses.Reduction\")\nclass Reduction:\n    AUTO = \"auto\"\n    NONE = \"none\"\n    SUM = \"sum\"\n    SUM_OVER_BATCH_SIZE = \"sum_over_batch_size\"\n\n    @classmethod\n    def all(cls):\n        return (cls.AUTO, cls.NONE, cls.SUM, cls.SUM_OVER_BATCH_SIZE)\n\n    @classmethod\n    def validate(cls, key):\n        if key not in cls.all():\n            raise ValueError(\n                f'Invalid Reduction Key: {key}. Expected keys are \"{cls.all()}\"'\n            )\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/losses.py#L1-L21","documentation":"Keras legacy losses validate the reduction argument against the allowed ReductionV2 keys (auto, none, sum, sum_over_batch_size). Passing anything else - e.g. the Keras 1 style 'sum_over_batch' or a string with wrong casing - raises this ValueError. It exists because reduction controls how per-sample losses are aggregated and an unrecognized key would silently change training math.","triggerScenarios":"Calling keras.losses.* or a legacy loss class with reduction='sum_over_batch', 'mean', 'SUM', or a custom string; restoring reduction from a saved config/JSON that contains an outdated key.","commonSituations":"Migrating old Keras/TF 1.x scripts, loading models from JSON configs saved by older versions, mixing TF1/TF2 enums and strings.","solutions":["Use one of the valid keys: 'auto', 'none', 'sum', or 'sum_over_batch_size'","If loading a saved config, map legacy values: 'sum_over_batch' -> 'sum_over_batch_size', 'mean' -> 'sum_over_batch_size'","Pass tf.keras.losses.Reduction enum members (Reduction.SUM_OVER_BATCH_SIZE) instead of raw strings"],"exampleFix":"# before\nloss = keras.losses.CategoricalCrossentropy(reduction='sum_over_batch')\n\n# after\nloss = keras.losses.CategoricalCrossentropy(reduction='sum_over_batch_size')","handlingStrategy":"validation","validationCode":"from keras.src.legacy.losses import Reduction\nvalid = {'auto', 'none', 'sum', 'sum_over_batch_size'}\nassert reduction in valid | {r.value for r in Reduction}, reduction","typeGuard":"def is_valid_reduction(r) -> bool:\n    return r in {'auto', 'none', 'sum', 'sum_over_batch_size'}","tryCatchPattern":"try:\n    loss = Loss(reduction=reduction)\nexcept ValueError as e:\n    if 'Invalid Reduction Key' in str(e):\n        reduction = 'sum_over_batch_size'\n    else:\n        raise","preventionTips":["Normalize reduction values through one constant/config mapping","Validate config-derived strings against the whitelist at load time"],"tags":["keras","losses","reduction","invalid-argument"],"backgroundTag":"invalid-enum-value","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}