{"record":{"id":"f72e3d6547c4426b","repo":"eriklindernoren/ML-From-Scratch","slug":"notimplementederror","errorCode":null,"errorMessage":"NotImplementedError()","messagePattern":"NotImplementedError\\(\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"mlfromscratch/deep_learning/layers.py","lineNumber":27,"sourceCode":"\nclass Layer(object):\n\n    def set_input_shape(self, shape):\n        \"\"\" Sets the shape that the layer expects of the input in the forward\n        pass method \"\"\"\n        self.input_shape = shape\n\n    def layer_name(self):\n        \"\"\" The name of the layer. Used in model summary. \"\"\"\n        return self.__class__.__name__\n\n    def parameters(self):\n        \"\"\" The number of trainable parameters used by the layer \"\"\"\n        return 0\n\n    def forward_pass(self, X, training):\n        \"\"\" Propogates the signal forward in the network \"\"\"\n        raise NotImplementedError()\n\n    def backward_pass(self, accum_grad):\n        \"\"\" Propogates the accumulated gradient backwards in the network.\n        If the has trainable weights then these weights are also tuned in this method.\n        As input (accum_grad) it receives the gradient with respect to the output of the layer and\n        returns the gradient with respect to the output of the previous layer. \"\"\"\n        raise NotImplementedError()\n\n    def output_shape(self):\n        \"\"\" The shape of the output produced by forward_pass \"\"\"\n        raise NotImplementedError()\n\n\nclass Dense(Layer):\n    \"\"\"A fully-connected NN layer.\n    Parameters:\n    -----------\n    n_units: int","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/eriklindernoren/ML-From-Scratch/blob/a2806c6732eee8d27762edd6d864e0c179d8e9e8/mlfromscratch/deep_learning/layers.py#L9-L45","documentation":"This error is raised by the base Layer class's forward_pass method in mlfromscratch. It is an abstract-method stub: Layer is designed to be subclassed, and every concrete layer (Dense, Activation, etc.) must override forward_pass. Calling it on the base class (or on a custom layer that forgot to implement it) means no forward computation exists for that layer.","triggerScenarios":"Instantiating mlfromscratch.deep_learning.layers.Layer directly and passing it to a NeuralNetwork, or writing a custom layer subclass that does not define forward_pass(X, training) and running model.fit/predict, which invokes layer.forward_pass during the network's forward propagation.","commonSituations":"Developers creating custom layers who copy a subset of the API (e.g. implement only backward_pass), using the base Layer as a placeholder/no-op layer, or upgrading versions where the method signature changed to require the extra 'training' argument so an old override with a different name/signature no longer overrides it.","solutions":["Implement forward_pass(self, X, training) in your custom Layer subclass returning the layer's output for input X","If you wanted a pass-through layer, subclass Layer and make forward_pass return X unchanged","Don't instantiate the abstract Layer directly; use a concrete layer such as Dense","Check for typos in the method name (forward_pass, not forward) so the override actually replaces the stub"],"exampleFix":"// before\nclass MyLayer(Layer):\n    def forward(self, X):   # wrong name -> base stub raises\n        return X\n\n// after\nclass MyLayer(Layer):\n    def forward_pass(self, X, training=True):\n        return X  # custom forward computation\n\n    def backward_pass(self, accum_grad):\n        return accum_grad\n\n    def output_shape(self):\n        return self.input_shape","handlingStrategy":"type-guard","validationCode":"def layer_is_complete(layer):\n    return all(callable(getattr(layer, m, None)) and not _is_base_stub(layer, m)\n               for m in ('forward_pass', 'backward_pass', 'output_shape'))\n\ndef _is_base_stub(layer, method):\n    # the stubs only exist on the base Layer class\n    import mlfromscratch.deep_learning.layers as L\n    return getattr(type(layer), method, None) is getattr(L.Layer, method, None)\n\nfor layer in model.layers:\n    assert layer_is_complete(layer), f'{type(layer).__name__} is missing required Layer methods'","typeGuard":"from mlfromscratch.deep_learning.layers import Layer\n\ndef is_fully_implemented_layer(obj) -> bool:\n    if not isinstance(obj, Layer):\n        return False\n    for m in ('forward_pass', 'backward_pass', 'output_shape'):\n        fn = getattr(type(obj), m, None)\n        if fn is None or fn is getattr(Layer, m, None):\n            return False\n    return True","tryCatchPattern":null,"preventionTips":["Never instantiate the abstract Layer directly; always use or derive a concrete subclass","When creating custom layers, implement all three methods: forward_pass(X, training), backward_pass(accum_grad), output_shape()","Run a one-layer smoke test (single forward + backward on tiny data) before wiring a custom layer into a full model","Pin the library version so method signatures like the 'training' argument don't change under you"],"tags":["python","deep-learning","abstract-method","not-implemented","inheritance"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"a2806c6732eee8d27762edd6d864e0c179d8e9e8","analyzedAt":"2026-08-27T20:30:03.909Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}