Misusing of NotImplementedError in Ruby

Common mistakes and existing alternatives

Kirill Shevchenko
3 min readNov 13, 2023

Have you ever come across code that raises a NotImplementedError when a method is not implemented in a class? It may seem like a convenient way to indicate that a method should be implemented, but actually it’s not.

Understanding NotImplementedError

According to the Ruby docs, NotImplementedError should be used when a feature is not implemented on the current platform. It’s typically used in operating-system-dependent methods to indicate that the current runtime platform does not support certain functionality.

For example, if a method depends on the fsync or fork system calls, raising a NotImplementedError would be appropriate if the underlying operating system or Ruby runtime doesn’t support them.

def save_data(data, file_path)
File.open(file_path, 'w') do |file|
file.write(data)
file.fsync
end
rescue NotImplementedError
raise 'The fsync system call is not supported on this OS.'
end

Confusion and Misuse

However, the name of the exception, NotImplementedError, can be misleading. Developers often misinterpret its purpose and use it in abstract methods or as a replacement for TODO comments. This misunderstanding has spread, leading to developers wrongly suggesting its use in situations where it doesn’t make sense. Also, NotImplementedError inherited from ScriptError , so it won’t be rescued:

Alternatives

Given the risks and potential confusion surrounding NotImplementedError, it is crucial to consider alternative approaches. While there is no universal consensus, here are three options that can be considered:

Use NoMethodError

Out of the existing Ruby exceptions, NoMethodError is the most appropriate for abstract methods. It clearly indicates that the method does not exist in the current context.

Example:

class AbstractClass
def some_undefined_method
raise NoMethodError.new('method not implemented in this class')
end
end

Raise a RuntimeError

If the situations where you encounter this error are expected to be rare, you may choose to raise a RuntimeError with a specific message. This allows you to provide a custom error message while still adhering to Ruby’s exception hierarchy.

Example:

class AbstractClass
def some_undefined_method
raise RuntimeError.new('method not implemented in this class')
end
end

Define a custom exception class

For more complex projects, it may be beneficial to define your own exception class and use it consistently throughout. For example, creating an CustomMethodError class that inherits from StandardError can provide clarity and consistency.

Example:

class CustomMethodError < StandardError
end

class AbstractClass
def some_undefined_method
raise CustomMethodError.new('method not implemented in this class')
end
end

Conclusion

The misuse of NotImplementedError in Ruby can lead to confusion and unexpected behavior. While the name may be appealing, it is essential to use this exception correctly in OS-dependent methods. For abstract methods or as a TODO replacement, alternative approaches like NoMethodError, RuntimeError, or a custom exception class are recommended.

--

--

Kirill Shevchenko

Software Engineer. Interested in Microservices, Distributed Systems and Cloud Services.