I agree this is a bit fuzzy. I know the practice, which is (just some examples):
ERROR: ArgumentError: Month: 0 out of range (1:12)
julia> parse(Int, 'a')
ERROR: ArgumentError: invalid base 10 digit 'a'
julia> parse(Int, "a")
ERROR: ArgumentError: invalid base 10 digit 'a' in "a"
ERROR: ArgumentError: Symbol name may not contain \0
and my favorite:
ERROR: ArgumentError: nothing passed to notnothing
which is defined as:
notnothing(::Nothing) = throw(ArgumentError("nothing passed to notnothing"))
which contradicts the interpretation from the docstring in 100% .
The practice I use in DataFrames.jl:
DomainError - when working with mathematical functions kind of stuff;
ArgumentError - all else
In theory (if we read the docstring precisely)
ArgumentError should be probably used when there is e.g.
::Any in the signature, but we dynamically check the type within the body of the function, but AFAICT this is not its typical use case in practice.
You also have
BoundsError which is also kind of
DomainError but specific for indexing operations.