{"record":{"id":"c6a4875afe10e9f3","repo":"keras-team/keras","slug":"all-cells-must-have-a-state-size-attribute-rece","errorCode":null,"errorMessage":"All cells must have a `state_size` attribute. Received cell without a `state_size`: {cell}","messagePattern":"All cells must have a `state_size` attribute\\. Received cell without a `state_size`: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/rnn/stacked_rnn_cells.py","lineNumber":43,"sourceCode":"\n    rnn_cells = [keras.layers.LSTMCell(128) for _ in range(2)]\n    stacked_lstm = keras.layers.StackedRNNCells(rnn_cells)\n    lstm_layer = keras.layers.RNN(stacked_lstm)\n\n    result = lstm_layer(x)\n    ```\n    \"\"\"\n\n    def __init__(self, cells, **kwargs):\n        super().__init__(**kwargs)\n        for cell in cells:\n            if \"call\" not in dir(cell):\n                raise ValueError(\n                    \"All cells must have a `call` method. \"\n                    f\"Received cell without a `call` method: {cell}\"\n                )\n            if \"state_size\" not in dir(cell):\n                raise ValueError(\n                    \"All cells must have a `state_size` attribute. \"\n                    f\"Received cell without a `state_size`: {cell}\"\n                )\n        self.cells = cells\n\n    @property\n    def state_size(self):\n        return [c.state_size for c in self.cells]\n\n    @property\n    def output_size(self):\n        if getattr(self.cells[-1], \"output_size\", None) is not None:\n            return self.cells[-1].output_size\n        elif isinstance(self.cells[-1].state_size, (list, tuple)):\n            return self.cells[-1].state_size[0]\n        else:\n            return self.cells[-1].state_size\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/rnn/stacked_rnn_cells.py#L25-L61","documentation":"StackedRNNCells requires every cell to expose a `state_size` attribute (checked via `dir(cell)` in `__init__`), because the RNN layer needs to know how many state tensors and their sizes to initialize and pass between timesteps. A cell with `call` but no `state_size` cannot be stepped by the RNN machinery, so construction aborts.","triggerScenarios":"Passing a custom object that implements call() but not state_size to keras.layers.StackedRNNCells(cells=[...]); porting a PyTorch-style RNN module or generic Layer into a Keras cell list.","commonSituations":"Writing custom RNN cells and forgetting state_size; migrating from tf.keras v1 or other frameworks whose cell interfaces differ; refactoring a Layer into a cell without adding the RNN cell contract.","solutions":["Add state_size to the custom cell, e.g. self.state_size = units for a single-state cell (or a tuple/list for multiple states)","If the object is not meant to be a cell, replace it with a proper Keras cell (SimpleRNNCell, LSTMCell, GRUCell)","For multi-state cells, make sure state_size lengths match what call() returns as new_states"],"exampleFix":"# before\nclass MyCell:\n    def __init__(self, units):\n        self.units = units\n    def call(self, inputs, states):\n        ...\n\n# after\nclass MyCell:\n    def __init__(self, units):\n        self.units = units\n        self.state_size = units\n    def call(self, inputs, states):\n        ...","handlingStrategy":"type-guard","validationCode":"assert all(hasattr(c, 'state_size') for c in cells), 'cells missing state_size'\nstacked = keras.layers.StackedRNNCells(cells=cells)","typeGuard":"def has_state_size(cell) -> bool:\n    return hasattr(cell, 'state_size') and cell.state_size is not None","tryCatchPattern":null,"preventionTips":["Add state_size whenever implementing a custom RNN cell","If state_size is a tuple, its length must equal the number of returned new_states"],"tags":["keras","rnn","custom-cell","state-size"],"backgroundTag":"missing-required-attribute","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}