Skip to main content

Errors

Now, it is the time to describe each result type. Let's start with errors.

What is an error?

Error is a result type caused either by the wrong input data (validation error) or by the exceptional behaviour (exception error).

In some cases, it may be a validation rule violation, unsatisfied assertion, or unmet precondition based on the service arguments.

It is a responsibility of a developer/service user to provide correct inputs.

Otherwise, there is no sense in even starting any service processing.

Also errors are often semantically close to the exceptions.

In other words, service errors are frequently located at the same places where exceptions are raised/rescued in the reqular methods.

info

Exceptional behaviour like HTTP connection issues, database inconsistencies, timeouts, etc are also errors.

Check out the following example:

class EnsureFeatureActive
# ...
def initialize(name:)
@name = name
end

def result
return error("Feature name can NOT be `nil`") if name.nil?
return error("Unknown feature `#{name}`") unless Feature.exist?(name: name)

# ... Tricky and non trivial logic to ensure that feature is active...
rescue Feature::Exceptions::ConnectionTimeout => exception
return error("Feature `#{name}` connection timeout due to `#{exception.message}`")
end
end

And this is how it can be triggerred:

result = EnsureFeatureActive.result(name: "Fancy feature")

if result.error?
# `result.message` is a string-like object with error reason.
result.message
end

There is no point to involve all the heavy machinery when the feature name is nil.

Why do we need to waste any expensive resources if the feature name is unknown?

Can we guarantee whether the feature is actually active when a connection timeout happens?

So, the one of the purposes of the error result is to say that the callers need to make adjustments in their code/config/dependency, not the service authors.