diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 4f32c5dc1d..1fc447511a 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -123,8 +123,9 @@ cube_in(PG_FUNCTION_ARGS)
 
 	cube_scanner_init(str, &scanbuflen);
 
-	cube_yyparse(&result, scanbuflen);
+	cube_yyparse(&result, scanbuflen, fcinfo->context);
 
+	/* We might as well run this even on failure. */
 	cube_scanner_finish();
 
 	PG_RETURN_NDBOX_P(result);
diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index 640a7ca580..96fa41a04e 100644
--- a/contrib/cube/cubedata.h
+++ b/contrib/cube/cubedata.h
@@ -61,9 +61,12 @@ typedef struct NDBOX
 
 /* in cubescan.l */
 extern int	cube_yylex(void);
-extern void cube_yyerror(NDBOX **result, Size scanbuflen, const char *message) pg_attribute_noreturn();
+extern void cube_yyerror(NDBOX **result, Size scanbuflen,
+						 struct Node *escontext,
+						 const char *message);
 extern void cube_scanner_init(const char *str, Size *scanbuflen);
 extern void cube_scanner_finish(void);
 
 /* in cubeparse.y */
-extern int	cube_yyparse(NDBOX **result, Size scanbuflen);
+extern int	cube_yyparse(NDBOX **result, Size scanbuflen,
+						 struct Node *escontext);
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index e6e361736c..44450d1027 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -7,6 +7,7 @@
 #include "postgres.h"
 
 #include "cubedata.h"
+#include "nodes/miscnodes.h"
 #include "utils/float.h"
 
 /* All grammar constructs return strings */
@@ -21,14 +22,17 @@
 #define YYFREE   pfree
 
 static int item_count(const char *s, char delim);
-static NDBOX *write_box(int dim, char *str1, char *str2);
-static NDBOX *write_point_as_box(int dim, char *str);
+static bool write_box(int dim, char *str1, char *str2,
+					  NDBOX **result, struct Node *escontext);
+static bool write_point_as_box(int dim, char *str,
+							   NDBOX **result, struct Node *escontext);
 
 %}
 
 /* BISON Declarations */
 %parse-param {NDBOX **result}
 %parse-param {Size scanbuflen}
+%parse-param {struct Node *escontext}
 %expect 0
 %name-prefix="cube_yy"
 
@@ -45,7 +49,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		dim = item_count($2, ',');
 		if (item_count($4, ',') != dim)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("Different point dimensions in (%s) and (%s).",
@@ -54,7 +58,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		}
 		if (dim > CUBE_MAX_DIM)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("A cube cannot have more than %d dimensions.",
@@ -62,7 +66,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 			YYABORT;
 		}
 
-		*result = write_box( dim, $2, $4 );
+		if (!write_box(dim, $2, $4, result, escontext))
+			YYABORT;
 	}
 
 	| paren_list COMMA paren_list
@@ -72,7 +77,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		dim = item_count($1, ',');
 		if (item_count($3, ',') != dim)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("Different point dimensions in (%s) and (%s).",
@@ -81,7 +86,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		}
 		if (dim > CUBE_MAX_DIM)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("A cube cannot have more than %d dimensions.",
@@ -89,7 +94,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 			YYABORT;
 		}
 
-		*result = write_box( dim, $1, $3 );
+		if (!write_box(dim, $1, $3, result, escontext))
+			YYABORT;
 	}
 
 	| paren_list
@@ -99,7 +105,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		dim = item_count($1, ',');
 		if (dim > CUBE_MAX_DIM)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("A cube cannot have more than %d dimensions.",
@@ -107,7 +113,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 			YYABORT;
 		}
 
-		*result = write_point_as_box(dim, $1);
+		if (!write_point_as_box(dim, $1, result, escontext))
+			YYABORT;
 	}
 
 	| list
@@ -117,7 +124,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 		dim = item_count($1, ',');
 		if (dim > CUBE_MAX_DIM)
 		{
-			ereport(ERROR,
+			errsave(escontext,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for cube"),
 					 errdetail("A cube cannot have more than %d dimensions.",
@@ -125,7 +132,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
 			YYABORT;
 		}
 
-		*result = write_point_as_box(dim, $1);
+		if (!write_point_as_box(dim, $1, result, escontext))
+			YYABORT;
 	}
 	;
 
@@ -173,8 +181,9 @@ item_count(const char *s, char delim)
 	return nitems;
 }
 
-static NDBOX *
-write_box(int dim, char *str1, char *str2)
+static bool
+write_box(int dim, char *str1, char *str2,
+		  NDBOX **result, struct Node *escontext)
 {
 	NDBOX	   *bp;
 	char	   *s;
@@ -190,18 +199,26 @@ write_box(int dim, char *str1, char *str2)
 	s = str1;
 	i = 0;
 	if (dim > 0)
-		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, NULL);
+	{
+		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
+	}
 	while ((s = strchr(s, ',')) != NULL)
 	{
 		s++;
-		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, NULL);
+		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
 	}
 	Assert(i == dim);
 
 	s = str2;
 	if (dim > 0)
 	{
-		bp->x[i] = float8in_internal(s, &endptr, "cube", str2, NULL);
+		bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
 		/* code this way to do right thing with NaN */
 		point &= (bp->x[i] == bp->x[0]);
 		i++;
@@ -209,7 +226,9 @@ write_box(int dim, char *str1, char *str2)
 	while ((s = strchr(s, ',')) != NULL)
 	{
 		s++;
-		bp->x[i] = float8in_internal(s, &endptr, "cube", str2, NULL);
+		bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
 		point &= (bp->x[i] == bp->x[i - dim]);
 		i++;
 	}
@@ -229,11 +248,13 @@ write_box(int dim, char *str1, char *str2)
 		SET_POINT_BIT(bp);
 	}
 
-	return bp;
+	*result = bp;
+	return true;
 }
 
-static NDBOX *
-write_point_as_box(int dim, char *str)
+static bool
+write_point_as_box(int dim, char *str,
+				   NDBOX **result, struct Node *escontext)
 {
 	NDBOX		*bp;
 	int			i,
@@ -250,13 +271,20 @@ write_point_as_box(int dim, char *str)
 	s = str;
 	i = 0;
 	if (dim > 0)
-		bp->x[i++] = float8in_internal(s, &endptr, "cube", str, NULL);
+	{
+		bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
+	}
 	while ((s = strchr(s, ',')) != NULL)
 	{
 		s++;
-		bp->x[i++] = float8in_internal(s, &endptr, "cube", str, NULL);
+		bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			return false;
 	}
 	Assert(i == dim);
 
-	return bp;
+	*result = bp;
+	return true;
 }
diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index 6b316f2d54..49cb699216 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -72,11 +72,13 @@ NaN          [nN][aA][nN]
 
 /* result and scanbuflen are not used, but Bison expects this signature */
 void
-cube_yyerror(NDBOX **result, Size scanbuflen, const char *message)
+cube_yyerror(NDBOX **result, Size scanbuflen,
+			 struct Node *escontext,
+			 const char *message)
 {
 	if (*yytext == YY_END_OF_BUFFER_CHAR)
 	{
-		ereport(ERROR,
+		errsave(escontext,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 				 /* translator: %s is typically "syntax error" */
@@ -84,7 +86,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen, const char *message)
 	}
 	else
 	{
-		ereport(ERROR,
+		errsave(escontext,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 				 /* translator: first %s is typically "syntax error" */
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 5b89cb1a26..dc23e5ccc0 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -325,6 +325,31 @@ SELECT '-1e-700'::cube AS cube; -- out of range
 ERROR:  "-1e-700" is out of range for type double precision
 LINE 1: SELECT '-1e-700'::cube AS cube;
                ^
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('(1,2)', 'cube');
+ pg_input_is_valid 
+-------------------
+ t
+(1 row)
+
+SELECT pg_input_is_valid('[(1),]', 'cube');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_is_valid('-1e-700', 'cube');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('-1e-700', 'cube');
+               pg_input_error_message                
+-----------------------------------------------------
+ "-1e-700" is out of range for type double precision
+(1 row)
+
 --
 -- Testing building cubes from float8 values
 --
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
index 7f8b2e3979..384883d16e 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -79,6 +79,12 @@ SELECT '1,2a'::cube AS cube; -- 7
 SELECT '1..2'::cube AS cube; -- 7
 SELECT '-1e-700'::cube AS cube; -- out of range
 
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('(1,2)', 'cube');
+SELECT pg_input_is_valid('[(1),]', 'cube');
+SELECT pg_input_is_valid('-1e-700', 'cube');
+SELECT pg_input_error_message('-1e-700', 'cube');
+
 --
 -- Testing building cubes from float8 values
 --
