diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 307d087c97..ed26cfba2d 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -120,6 +120,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	char	   *input_str = PG_GETARG_CSTRING(0);
 	Oid			mltrngtypoid = PG_GETARG_OID(1);
 	Oid			typmod = PG_GETARG_INT32(2);
+	Node	   *escontext = fcinfo->context;
 	TypeCacheEntry *rangetyp;
 	int32		ranges_seen = 0;
 	int32		range_count = 0;
@@ -133,6 +134,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	const char *range_str_begin = NULL;
 	int32		range_str_len;
 	char	   *range_str;
+	Datum		range_datum;
 
 	cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_input);
 	rangetyp = cache->typcache->rngtype;
@@ -144,7 +146,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	if (*ptr == '{')
 		ptr++;
 	else
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed multirange literal: \"%s\"",
 						input_str),
@@ -157,7 +159,7 @@ multirange_in(PG_FUNCTION_ARGS)
 		char		ch = *ptr;
 
 		if (ch == '\0')
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed multirange literal: \"%s\"",
 							input_str),
@@ -186,7 +188,7 @@ multirange_in(PG_FUNCTION_ARGS)
 					parse_state = MULTIRANGE_AFTER_RANGE;
 				}
 				else
-					ereport(ERROR,
+					ereturn(escontext, (Datum) 0,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed multirange literal: \"%s\"",
 									input_str),
@@ -204,10 +206,14 @@ multirange_in(PG_FUNCTION_ARGS)
 							repalloc(ranges, range_capacity * sizeof(RangeType *));
 					}
 					ranges_seen++;
-					range = DatumGetRangeTypeP(InputFunctionCall(&cache->typioproc,
-																 range_str,
-																 cache->typioparam,
-																 typmod));
+					if (!InputFunctionCallSafe(&cache->typioproc,
+											   range_str,
+											   cache->typioparam,
+											   typmod,
+											   escontext,
+											   &range_datum))
+						PG_RETURN_NULL();
+					range = DatumGetRangeTypeP(range_datum);
 					if (!RangeIsEmpty(range))
 						ranges[range_count++] = range;
 					parse_state = MULTIRANGE_AFTER_RANGE;
@@ -256,7 +262,7 @@ multirange_in(PG_FUNCTION_ARGS)
 				else if (ch == '}')
 					parse_state = MULTIRANGE_FINISHED;
 				else
-					ereport(ERROR,
+					ereturn(escontext, (Datum) 0,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed multirange literal: \"%s\"",
 									input_str),
@@ -280,7 +286,7 @@ multirange_in(PG_FUNCTION_ARGS)
 		ptr++;
 
 	if (*ptr != '\0')
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed multirange literal: \"%s\"",
 						input_str),
@@ -807,7 +813,7 @@ multirange_get_union_range(TypeCacheEntry *rangetyp,
 	multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
 	multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
 
-	return make_range(rangetyp, &lower, &upper, false);
+	return make_range(rangetyp, &lower, &upper, false, NULL);
 }
 
 
@@ -2696,7 +2702,8 @@ range_merge_from_multirange(PG_FUNCTION_ARGS)
 		multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
 							  &lastLower, &lastUpper);
 
-		result = make_range(typcache->rngtype, &firstLower, &lastUpper, false);
+		result = make_range(typcache->rngtype, &firstLower, &lastUpper,
+							false, NULL);
 	}
 
 	PG_RETURN_RANGE_P(result);
diff --git a/src/backend/utils/adt/multirangetypes_selfuncs.c b/src/backend/utils/adt/multirangetypes_selfuncs.c
index 919c8889d4..8fd6250e4a 100644
--- a/src/backend/utils/adt/multirangetypes_selfuncs.c
+++ b/src/backend/utils/adt/multirangetypes_selfuncs.c
@@ -221,7 +221,8 @@ multirangesel(PG_FUNCTION_ARGS)
 			upper.val = ((Const *) other)->constvalue;
 			upper.infinite = false;
 			upper.lower = false;
-			constrange = range_serialize(typcache->rngtype, &lower, &upper, false);
+			constrange = range_serialize(typcache->rngtype, &lower, &upper,
+										 false, NULL);
 			constmultirange = make_multirange(typcache->type_id, typcache->rngtype,
 											  1, &constrange);
 		}
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index b09cb49054..b89b07a710 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -35,6 +35,7 @@
 #include "lib/stringinfo.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
+#include "nodes/miscnodes.h"
 #include "port/pg_bitutils.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
@@ -55,10 +56,11 @@ typedef struct RangeIOData
 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
 									  IOFuncSelector func);
 static char range_parse_flags(const char *flags_str);
-static void range_parse(const char *string, char *flags, char **lbound_str,
-						char **ubound_str);
+static bool range_parse(const char *string, char *flags, char **lbound_str,
+						char **ubound_str, Node *escontext);
 static const char *range_parse_bound(const char *string, const char *ptr,
-									 char **bound_str, bool *infinite);
+									 char **bound_str, bool *infinite,
+									 Node *escontext);
 static char *range_deparse(char flags, const char *lbound_str,
 						   const char *ubound_str);
 static char *range_bound_escape(const char *value);
@@ -80,6 +82,7 @@ range_in(PG_FUNCTION_ARGS)
 	char	   *input_str = PG_GETARG_CSTRING(0);
 	Oid			rngtypoid = PG_GETARG_OID(1);
 	Oid			typmod = PG_GETARG_INT32(2);
+	Node	   *escontext = fcinfo->context;
 	RangeType  *range;
 	RangeIOData *cache;
 	char		flags;
@@ -93,15 +96,20 @@ range_in(PG_FUNCTION_ARGS)
 	cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
 
 	/* parse */
-	range_parse(input_str, &flags, &lbound_str, &ubound_str);
+	if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
+		PG_RETURN_NULL();
 
 	/* call element type's input function */
 	if (RANGE_HAS_LBOUND(flags))
-		lower.val = InputFunctionCall(&cache->typioproc, lbound_str,
-									  cache->typioparam, typmod);
+		if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
+								   cache->typioparam, typmod,
+								   escontext, &lower.val))
+			PG_RETURN_NULL();
 	if (RANGE_HAS_UBOUND(flags))
-		upper.val = InputFunctionCall(&cache->typioproc, ubound_str,
-									  cache->typioparam, typmod);
+		if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
+								   cache->typioparam, typmod,
+								   escontext, &upper.val))
+			PG_RETURN_NULL();
 
 	lower.infinite = (flags & RANGE_LB_INF) != 0;
 	lower.inclusive = (flags & RANGE_LB_INC) != 0;
@@ -111,7 +119,8 @@ range_in(PG_FUNCTION_ARGS)
 	upper.lower = false;
 
 	/* serialize and canonicalize */
-	range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
+	range = make_range(cache->typcache, &lower, &upper,
+					   flags & RANGE_EMPTY, escontext);
 
 	PG_RETURN_RANGE_P(range);
 }
@@ -234,7 +243,8 @@ range_recv(PG_FUNCTION_ARGS)
 	upper.lower = false;
 
 	/* serialize and canonicalize */
-	range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
+	range = make_range(cache->typcache, &lower, &upper,
+					   flags & RANGE_EMPTY, NULL);
 
 	PG_RETURN_RANGE_P(range);
 }
@@ -378,7 +388,7 @@ range_constructor2(PG_FUNCTION_ARGS)
 	upper.inclusive = false;
 	upper.lower = false;
 
-	range = make_range(typcache, &lower, &upper, false);
+	range = make_range(typcache, &lower, &upper, false, NULL);
 
 	PG_RETURN_RANGE_P(range);
 }
@@ -415,7 +425,7 @@ range_constructor3(PG_FUNCTION_ARGS)
 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
 	upper.lower = false;
 
-	range = make_range(typcache, &lower, &upper, false);
+	range = make_range(typcache, &lower, &upper, false, NULL);
 
 	PG_RETURN_RANGE_P(range);
 }
@@ -766,7 +776,7 @@ bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
 		/* change upper/lower labels to avoid Assert failures */
 		boundA.lower = true;
 		boundB.lower = false;
-		r = make_range(typcache, &boundA, &boundB, false);
+		r = make_range(typcache, &boundA, &boundB, false, NULL);
 		return RangeIsEmpty(r);
 	}
 	else if (cmp == 0)
@@ -1012,14 +1022,14 @@ range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 	{
 		lower2.inclusive = !lower2.inclusive;
 		lower2.lower = false;	/* it will become the upper bound */
-		return make_range(typcache, &lower1, &lower2, false);
+		return make_range(typcache, &lower1, &lower2, false, NULL);
 	}
 
 	if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
 	{
 		upper2.inclusive = !upper2.inclusive;
 		upper2.lower = true;	/* it will become the lower bound */
-		return make_range(typcache, &upper2, &upper1, false);
+		return make_range(typcache, &upper2, &upper1, false, NULL);
 	}
 
 	elog(ERROR, "unexpected case in range_minus");
@@ -1073,7 +1083,7 @@ range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
 	else
 		result_upper = &upper2;
 
-	return make_range(typcache, result_lower, result_upper, false);
+	return make_range(typcache, result_lower, result_upper, false, NULL);
 }
 
 Datum
@@ -1149,7 +1159,7 @@ range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ra
 	else
 		result_upper = &upper2;
 
-	return make_range(typcache, result_lower, result_upper, false);
+	return make_range(typcache, result_lower, result_upper, false, NULL);
 }
 
 /* range, range -> range, range functions */
@@ -1187,8 +1197,8 @@ range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeT
 		upper2.inclusive = !upper2.inclusive;
 		upper2.lower = true;
 
-		*output1 = make_range(typcache, &lower1, &lower2, false);
-		*output2 = make_range(typcache, &upper2, &upper1, false);
+		*output1 = make_range(typcache, &lower1, &lower2, false, NULL);
+		*output2 = make_range(typcache, &upper2, &upper1, false, NULL);
 		return true;
 	}
 
@@ -1470,7 +1480,7 @@ int4range_canonical(PG_FUNCTION_ARGS)
 		upper.inclusive = false;
 	}
 
-	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
+	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false, NULL));
 }
 
 Datum
@@ -1501,7 +1511,7 @@ int8range_canonical(PG_FUNCTION_ARGS)
 		upper.inclusive = false;
 	}
 
-	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
+	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false, NULL));
 }
 
 Datum
@@ -1534,7 +1544,7 @@ daterange_canonical(PG_FUNCTION_ARGS)
 		upper.inclusive = false;
 	}
 
-	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
+	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false, NULL));
 }
 
 /*
@@ -1657,7 +1667,7 @@ range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
  */
 RangeType *
 range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
-				bool empty)
+				bool empty, struct Node *escontext)
 {
 	RangeType  *range;
 	int			cmp;
@@ -1684,7 +1694,7 @@ range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
 
 		/* error check: if lower bound value is above upper, it's wrong */
 		if (cmp > 0)
-			ereport(ERROR,
+			ereturn(escontext, NULL,
 					(errcode(ERRCODE_DATA_EXCEPTION),
 					 errmsg("range lower bound must be less than or equal to range upper bound")));
 
@@ -1882,11 +1892,14 @@ range_set_contain_empty(RangeType *range)
  */
 RangeType *
 make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
-		   bool empty)
+		   bool empty, struct Node *escontext)
 {
 	RangeType  *range;
 
-	range = range_serialize(typcache, lower, upper, empty);
+	range = range_serialize(typcache, lower, upper, empty, escontext);
+
+	if (SOFT_ERROR_OCCURRED(escontext))
+		return NULL;
 
 	/* no need to call canonical on empty ranges ... */
 	if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
@@ -2085,7 +2098,7 @@ make_empty_range(TypeCacheEntry *typcache)
 	upper.inclusive = false;
 	upper.lower = false;
 
-	return make_range(typcache, &lower, &upper, true);
+	return make_range(typcache, &lower, &upper, true, NULL);
 }
 
 
@@ -2170,10 +2183,13 @@ range_parse_flags(const char *flags_str)
  * Within a <string>, special characters (such as comma, parenthesis, or
  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
  * double-quotes, a double-quote can be escaped with double-quote or backslash.
+ *
+ * Returns true on success, false on failure (but failures will return only if
+ * escontext is an ErrorSaveContext).
  */
-static void
+static bool
 range_parse(const char *string, char *flags, char **lbound_str,
-			char **ubound_str)
+			char **ubound_str, Node *escontext)
 {
 	const char *ptr = string;
 	bool		infinite;
@@ -2200,13 +2216,13 @@ range_parse(const char *string, char *flags, char **lbound_str,
 
 		/* should have consumed everything */
 		if (*ptr != '\0')
-			ereport(ERROR,
+			ereturn(escontext, false,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed range literal: \"%s\"",
 							string),
 					 errdetail("Junk after \"empty\" key word.")));
 
-		return;
+		return true;
 	}
 
 	if (*ptr == '[')
@@ -2217,26 +2233,30 @@ range_parse(const char *string, char *flags, char **lbound_str,
 	else if (*ptr == '(')
 		ptr++;
 	else
-		ereport(ERROR,
+		ereturn(escontext, false,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed range literal: \"%s\"",
 						string),
 				 errdetail("Missing left parenthesis or bracket.")));
 
-	ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
+	ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
+	if (ptr == NULL)
+		return false;
 	if (infinite)
 		*flags |= RANGE_LB_INF;
 
 	if (*ptr == ',')
 		ptr++;
 	else
-		ereport(ERROR,
+		ereturn(escontext, false,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed range literal: \"%s\"",
 						string),
 				 errdetail("Missing comma after lower bound.")));
 
-	ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
+	ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
+	if (ptr == NULL)
+		return false;
 	if (infinite)
 		*flags |= RANGE_UB_INF;
 
@@ -2248,7 +2268,7 @@ range_parse(const char *string, char *flags, char **lbound_str,
 	else if (*ptr == ')')
 		ptr++;
 	else						/* must be a comma */
-		ereport(ERROR,
+		ereturn(escontext, false,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed range literal: \"%s\"",
 						string),
@@ -2259,11 +2279,13 @@ range_parse(const char *string, char *flags, char **lbound_str,
 		ptr++;
 
 	if (*ptr != '\0')
-		ereport(ERROR,
+		ereturn(escontext, false,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed range literal: \"%s\"",
 						string),
 				 errdetail("Junk after right parenthesis or bracket.")));
+
+	return true;
 }
 
 /*
@@ -2279,10 +2301,11 @@ range_parse(const char *string, char *flags, char **lbound_str,
  *	*infinite: set true if no bound, else false
  *
  * The return value is the scan ptr, advanced past the bound string.
+ * However, if escontext is an ErrorSaveContext, we return NULL on failure.
  */
 static const char *
 range_parse_bound(const char *string, const char *ptr,
-				  char **bound_str, bool *infinite)
+				  char **bound_str, bool *infinite, Node *escontext)
 {
 	StringInfoData buf;
 
@@ -2303,7 +2326,7 @@ range_parse_bound(const char *string, const char *ptr,
 			char		ch = *ptr++;
 
 			if (ch == '\0')
-				ereport(ERROR,
+				ereturn(escontext, NULL,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("malformed range literal: \"%s\"",
 								string),
@@ -2311,7 +2334,7 @@ range_parse_bound(const char *string, const char *ptr,
 			if (ch == '\\')
 			{
 				if (*ptr == '\0')
-					ereport(ERROR,
+					ereturn(escontext, NULL,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed range literal: \"%s\"",
 									string),
diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c
index 5996de417d..771c81f67b 100644
--- a/src/backend/utils/adt/rangetypes_gist.c
+++ b/src/backend/utils/adt/rangetypes_gist.c
@@ -876,7 +876,7 @@ range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 		((flags2 & RANGE_CONTAIN_EMPTY) || !(flags1 & RANGE_CONTAIN_EMPTY)))
 		return r2;
 
-	result = make_range(typcache, result_lower, result_upper, false);
+	result = make_range(typcache, result_lower, result_upper, false, NULL);
 
 	if ((flags1 & RANGE_CONTAIN_EMPTY) || (flags2 & RANGE_CONTAIN_EMPTY))
 		range_set_contain_empty(result);
diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c
index c2795f4593..89114eba71 100644
--- a/src/backend/utils/adt/rangetypes_selfuncs.c
+++ b/src/backend/utils/adt/rangetypes_selfuncs.c
@@ -190,7 +190,7 @@ rangesel(PG_FUNCTION_ARGS)
 			upper.val = ((Const *) other)->constvalue;
 			upper.infinite = false;
 			upper.lower = false;
-			constrange = range_serialize(typcache, &lower, &upper, false);
+			constrange = range_serialize(typcache, &lower, &upper, false, NULL);
 		}
 	}
 	else if (operator == OID_RANGE_ELEM_CONTAINED_OP)
diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c
index a47f04d975..d4a4d35e60 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -265,7 +265,7 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 
 	/* Construct "centroid" range from medians of lower and upper bounds */
 	centroid = range_serialize(typcache, &lowerBounds[nonEmptyCount / 2],
-							   &upperBounds[nonEmptyCount / 2], false);
+							   &upperBounds[nonEmptyCount / 2], false, NULL);
 	out->hasPrefix = true;
 	out->prefixDatum = RangeTypePGetDatum(centroid);
 
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 2043d3f98b..f73c904b90 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -311,7 +311,8 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 				bound_hist_values[i] = PointerGetDatum(range_serialize(typcache,
 																	   &lowers[pos],
 																	   &uppers[pos],
-																	   false));
+																	   false,
+																	   NULL));
 				pos += delta;
 				posfrac += deltafrac;
 				if (posfrac >= (num_hist - 1))
diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h
index 2eee6a6c1f..3ae13cb9fb 100644
--- a/src/include/utils/rangetypes.h
+++ b/src/include/utils/rangetypes.h
@@ -143,14 +143,16 @@ extern RangeType *range_intersect_internal(TypeCacheEntry *typcache, const Range
 extern TypeCacheEntry *range_get_typcache(FunctionCallInfo fcinfo,
 										  Oid rngtypid);
 extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
-								  RangeBound *upper, bool empty);
+								  RangeBound *upper, bool empty,
+								  struct Node *escontext);
 extern void range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
 							  RangeBound *lower, RangeBound *upper,
 							  bool *empty);
 extern char range_get_flags(const RangeType *range);
 extern void range_set_contain_empty(RangeType *range);
 extern RangeType *make_range(TypeCacheEntry *typcache, RangeBound *lower,
-							 RangeBound *upper, bool empty);
+							 RangeBound *upper, bool empty,
+							 struct Node *escontext);
 extern int	range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1,
 							 const RangeBound *b2);
 extern int	range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
diff --git a/src/test/regress/expected/multirangetypes.out b/src/test/regress/expected/multirangetypes.out
index ac2eb84c3a..14aa4c46cd 100644
--- a/src/test/regress/expected/multirangetypes.out
+++ b/src/test/regress/expected/multirangetypes.out
@@ -274,6 +274,37 @@ select '{(a,a)}'::textmultirange;
  {}
 (1 row)
 
+-- Also try it with non-error-throwing API
+select pg_input_is_valid('{[1,2], [4,5]}', 'int4multirange');
+ pg_input_is_valid 
+-------------------
+ t
+(1 row)
+
+select pg_input_is_valid('{[1,2], [4,5]', 'int4multirange');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+select pg_input_error_message('{[1,2], [4,5]', 'int4multirange');
+            pg_input_error_message             
+-----------------------------------------------
+ malformed multirange literal: "{[1,2], [4,5]"
+(1 row)
+
+select pg_input_is_valid('{[1,2], [4,zed]}', 'int4multirange');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+select pg_input_error_message('{[1,2], [4,zed]}', 'int4multirange');
+            pg_input_error_message            
+----------------------------------------------
+ invalid input syntax for type integer: "zed"
+(1 row)
+
 --
 -- test the constructor
 ---
diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out
index 04ccd5d451..45b54adbed 100644
--- a/src/test/regress/expected/rangetypes.out
+++ b/src/test/regress/expected/rangetypes.out
@@ -175,6 +175,49 @@ select '(a,a)'::textrange;
  empty
 (1 row)
 
+-- Also try it with non-error-throwing API
+select pg_input_is_valid('(1,4)', 'int4range');
+ pg_input_is_valid 
+-------------------
+ t
+(1 row)
+
+select pg_input_is_valid('(1,4', 'int4range');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+select pg_input_error_message('(1,4', 'int4range');
+     pg_input_error_message      
+---------------------------------
+ malformed range literal: "(1,4"
+(1 row)
+
+select pg_input_is_valid('(4,1)', 'int4range');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+select pg_input_error_message('(4,1)', 'int4range');
+                      pg_input_error_message                       
+-------------------------------------------------------------------
+ range lower bound must be less than or equal to range upper bound
+(1 row)
+
+select pg_input_is_valid('(4,zed)', 'int4range');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+select pg_input_error_message('(4,zed)', 'int4range');
+            pg_input_error_message            
+----------------------------------------------
+ invalid input syntax for type integer: "zed"
+(1 row)
+
 --
 -- create some test data and test the operators
 --
diff --git a/src/test/regress/sql/multirangetypes.sql b/src/test/regress/sql/multirangetypes.sql
index 1abcaeddb5..78a650eb0f 100644
--- a/src/test/regress/sql/multirangetypes.sql
+++ b/src/test/regress/sql/multirangetypes.sql
@@ -58,6 +58,13 @@ select '{[a,a)}'::textmultirange;
 select '{(a,a]}'::textmultirange;
 select '{(a,a)}'::textmultirange;
 
+-- Also try it with non-error-throwing API
+select pg_input_is_valid('{[1,2], [4,5]}', 'int4multirange');
+select pg_input_is_valid('{[1,2], [4,5]', 'int4multirange');
+select pg_input_error_message('{[1,2], [4,5]', 'int4multirange');
+select pg_input_is_valid('{[1,2], [4,zed]}', 'int4multirange');
+select pg_input_error_message('{[1,2], [4,zed]}', 'int4multirange');
+
 --
 -- test the constructor
 ---
diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql
index 1a10f67f19..d786c8f5bd 100644
--- a/src/test/regress/sql/rangetypes.sql
+++ b/src/test/regress/sql/rangetypes.sql
@@ -40,6 +40,15 @@ select '[a,a)'::textrange;
 select '(a,a]'::textrange;
 select '(a,a)'::textrange;
 
+-- Also try it with non-error-throwing API
+select pg_input_is_valid('(1,4)', 'int4range');
+select pg_input_is_valid('(1,4', 'int4range');
+select pg_input_error_message('(1,4', 'int4range');
+select pg_input_is_valid('(4,1)', 'int4range');
+select pg_input_error_message('(4,1)', 'int4range');
+select pg_input_is_valid('(4,zed)', 'int4range');
+select pg_input_error_message('(4,zed)', 'int4range');
+
 --
 -- create some test data and test the operators
 --
