SFINAE stands for Substitution Failure Is Not An Error. Ill-formed code that results from substituting types (or values) to instantiate a function template or a class template is not a hard compile error, it is only treated as a deduction failure.
Deduction failures on instantiating function templates or class template specializations remove that candidate from the set of consideration - as if that failed candidate did not exist to begin with.
template <class T>
auto begin(T& c) -> decltype(c.begin()) { return c.begin(); }
template <class T, size_t N>
T* begin(T (&arr)[N]) { return arr; }
int vals[10];
begin(vals); // OK. The first function template substitution fails because
// vals.begin() is ill-formed. This is not an error! That function
// is just removed from consideration as a viable overload candidate,
// leaving us with the array overload.
Only substitution failures in the immediate context are considered deduction failures, all others are considered hard errors.
template <class T>
void add_one(T& val) { val += 1; }
int i = 4;
add_one(i); // ok
std::string msg = "Hello";
add_one(msg); // error. msg += 1 is ill-formed for std::string, but this
// failure is NOT in the immediate context of substituting T