A math domain error is a runtime exception raised when a numerical function is called outside its mathematical domain. In Python, the most common shape is ValueError: math domain error, triggered by operations like sqrt(-1), log(0), or 1/0. The right fix is to validate the input before calling the function, not to catch the exception and ignore it.
Table of contents
- What the term means
- Where domain errors come from
- The right fix
- Domain errors in HTTP APIs
- Domain errors vs type errors vs range errors
- The error handling patterns
- Domain errors in databases
- FAQ
What the term means
In mathematics, a function has a domain (the set of inputs it accepts) and a range (the set of outputs it produces). A “domain error” is when the function is called with an input outside its domain.
Examples:
sqrt(-1)is a domain error for the real-valued square root function.log(0)is a domain error for the natural logarithm.1/0is a domain error for division.INT_MAX + 1is a domain error for a 32-bit integer.
In programming, these usually raise an exception (ValueError, ZeroDivisionError, OverflowError) or return a special value (NaN, Infinity).
Where domain errors come from
The four common sources:
- Math libraries.
sqrt,log,sin, etc. all have domain restrictions. Most languages throw an exception when the input is outside the domain. - Type errors. A function expects a string, gets an integer. The function throws a TypeError or coerces the input (with unexpected results).
- Boundary conditions. An empty array, a negative index, an integer overflow. The function throws an exception or returns garbage.
- API constraints. A function expects a value in a specific range (a percentage in [0, 100], an HTTP status code in [100, 599]). The function throws when the input is outside the range.
The right fix
The right fix for a domain error:
- Validate the input before calling the function. Don’t wait for the exception.
- Return a clear error. If the input is invalid, return a 400 with a descriptive error message.
- Don’t catch and ignore. A
try { ... } catch { }block hides the bug; the team should log the error and return a clear error to the caller.
The team that catches the exception and ignores it has a bug that shows up later in a weirder place.
Domain errors in HTTP APIs
In an HTTP API, a domain error usually maps to:
- 400 Bad Request. The input is invalid. The fix: validate at the edge of the API.
- 422 Unprocessable Entity. The input is well-formed but semantically invalid. The fix: validate the business rules.
- 500 Internal Server Error. A domain error that wasn’t caught. The fix: handle the specific exception type and return a meaningful response.
The team that returns 500 for every domain error is the team that has unhandled exceptions in the request path.
Domain errors vs type errors vs range errors
Three related concepts:
- Domain error. The input is outside the function’s domain.
sqrt(-1). - Type error. The input is the wrong type.
sqrt("hello"). - Range error. The output is outside the representable range.
100000 * 100000in a 32-bit integer overflows.
In practice, the line between them is blurry. Most languages throw a ValueError or MathError for all three.
The error handling patterns
The right way to handle domain errors in production code:
Validate at the edge. The API receives input; the first thing it does is validate. Invalid input returns a 400 with a descriptive error message.
Specific exception types. Each error condition has a specific exception type (InvalidEmailError, OutOfStockError). The handler catches the specific type and returns a meaningful response.
Centralized error handler. The application has one place that converts exceptions to HTTP responses. Routes don’t have try/catch blocks for every domain error; they let exceptions propagate to the central handler.
Logging. Every domain error is logged with context (user ID, request ID, input summary). The team that has logs can debug issues without asking the user.
Monitoring. The team that alerts on domain error rates (e.g., 4xx responses exceeding a threshold) catches issues before users complain.
Domain errors in databases
Database queries have their own domain error patterns:
- Unique constraint violations. PostgreSQL raises
UniqueViolation. The right fix: catch the exception, return a 409 Conflict to the user. - Foreign key violations.
ForeignKeyViolation. The right fix: validate the foreign key exists before the insert. - Check constraint violations.
CheckViolation. The right fix: validate the value at the application layer. - Not null violations.
NotNullViolation. The right fix: validate the value is not null before the insert.
The team that catches specific exception types has meaningful error responses. The team that catches the generic Exception type returns 500 for everything.
FAQ
What’s a domain error in JavaScript?
Most often a RangeError or TypeError. Math.sqrt(-1) returns NaN; parseInt("hello") returns NaN; (1/0) returns Infinity.
Should I catch domain errors?
Yes, but handle them. The team that catches the exception and returns a clear 400 to the caller has the right pattern. The team that catches and ignores has a bug that shows up later.
What’s the difference between domain error and bug?
A domain error is an expected failure mode (the input is outside the function’s domain). A bug is an unexpected failure (the function is supposed to handle the input but doesn’t). The team that handles both differently has a clear error model.
How do I prevent domain errors?
Validate at the edge of the system. Reject invalid input with a 400 before the function is called. The team that validates early has fewer exceptions in the request path.
What’s the difference between domain error and bug?
Domain error is an expected failure (input outside the function’s domain). Bug is an unexpected failure (the function doesn’t handle valid input correctly). The team that handles both differently has a clear error model.
Should I use exceptions or Result types for domain errors?
Exceptions are the default in most languages (Python, Java, JavaScript). Result types are common in Rust and functional languages. The team that uses exceptions has the more familiar pattern; the team that uses Result types has more explicit error handling.
How do I log domain errors without alerting on every one?
Log every domain error at INFO or WARN level. Alert on the rate, not on individual errors. The team that alerts on every error has alert fatigue; the team that alerts on rate catches trends.
If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.
Useful related references: