diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 075c81b558..0dea35a981 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -4559,7 +4559,7 @@ ExecInitJsonItemCoercions(ExprEvalStep *scratch, ExprState *state,
 		scratch->opcode = EEOP_JUMP;
 
 		/*
-		 * Remember JUMP step address to set the actual jump target addreess
+		 * Remember JUMP step address to set the actual jump target address
 		 * below.
 		 */
 		adjust_jumps = lappend_int(adjust_jumps, state->steps_len);
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index dc255354f0..50a3d5d7fa 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -265,7 +265,6 @@ typedef struct PopulateArrayContext
 	int		   *sizes;			/* current dimension counters */
 	int			ndims;			/* number of dimensions */
 	Node	   *escontext;		/* For soft-error capture */
-	bool		error;			/* Caught a soft-error? */
 } PopulateArrayContext;
 
 /* state for populate_array_json() */
@@ -461,7 +460,8 @@ static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims);
 static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim);
 static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv);
 static Datum populate_array(ArrayIOData *aio, const char *colname,
-							MemoryContext mcxt, JsValue *jsv, Node *escontext);
+							MemoryContext mcxt, JsValue *jsv, Node *escontext,
+							bool *isnull);
 static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname,
 							 MemoryContext mcxt, JsValue *jsv, bool isnull);
 
@@ -2520,11 +2520,13 @@ populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
 					 errhint("See the array element %s.",
 							 indices.data)));
 	}
-
-	ctx->error = SOFT_ERROR_OCCURRED(ctx->escontext);
 }
 
-/* set the number of dimensions of the populated array when it becomes known */
+/*
+ * Set the number of dimensions of the populated array when it becomes known.
+ *
+ * Returns without doing anything if the input (ndims) is erratic.
+ */
 static void
 populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
 {
@@ -2535,7 +2537,8 @@ populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
 	if (ndims <= 0)
 		populate_array_report_expected_array(ctx, ndims);
 
-	if (ctx->error)
+	/* Nothing to do on an error. */
+	if (SOFT_ERROR_OCCURRED(ctx->escontext))
 		return;
 
 	ctx->ndims = ndims;
@@ -2561,6 +2564,10 @@ populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
 				 errdetail("Multidimensional arrays must have "
 						   "sub-arrays with matching dimensions.")));
 
+	/* Nothing to do on an error. */
+	if (SOFT_ERROR_OCCURRED(ctx->escontext))
+		return;
+
 	/* reset the current array dimension size counter */
 	ctx->sizes[ndim] = 0;
 
@@ -2580,7 +2587,10 @@ populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
 									ctx->aio->element_type,
 									ctx->aio->element_typmod,
 									NULL, ctx->mcxt, PointerGetDatum(NULL),
-									jsv, &element_isnull, NULL);
+									jsv, &element_isnull, ctx->escontext);
+	/* Nothing to do on an error. */
+	if (SOFT_ERROR_OCCURRED(ctx->escontext))
+		return;
 
 	accumArrayResult(ctx->astate, element, element_isnull,
 					 ctx->aio->element_type, ctx->acxt);
@@ -2601,6 +2611,10 @@ populate_array_object_start(void *_state)
 	else if (ndim < state->ctx->ndims)
 		populate_array_report_expected_array(state->ctx, ndim);
 
+	/* Report that an error occurred. */
+	if (SOFT_ERROR_OCCURRED(state->ctx->escontext))
+		return JSON_SEM_ACTION_FAILED;
+
 	return JSON_SUCCESS;
 }
 
@@ -2618,6 +2632,10 @@ populate_array_array_end(void *_state)
 	if (ndim < ctx->ndims)
 		populate_array_check_dimension(ctx, ndim);
 
+	/* Report that an error occurred. */
+	if (SOFT_ERROR_OCCURRED(state->ctx->escontext))
+		return JSON_SEM_ACTION_FAILED;
+
 	return JSON_SUCCESS;
 }
 
@@ -2693,6 +2711,10 @@ populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
 	else if (ndim < ctx->ndims)
 		populate_array_report_expected_array(ctx, ndim);
 
+	/* Report that an error occurred. */
+	if (SOFT_ERROR_OCCURRED(ctx->escontext))
+		return JSON_SEM_ACTION_FAILED;
+
 	if (ndim == ctx->ndims)
 	{
 		/* remember the scalar element token */
@@ -2722,7 +2744,13 @@ populate_array_json(PopulateArrayContext *ctx, char *json, int len)
 	sem.array_element_end = populate_array_element_end;
 	sem.scalar = populate_array_scalar;
 
-	pg_parse_json_or_errsave(state.lex, &sem, ctx->escontext);
+	if (!pg_parse_json_or_errsave(state.lex, &sem, ctx->escontext))
+	{
+		/* Nothing to do on an error. */
+		Assert(SOFT_ERROR_OCCURRED(ctx->escontext));
+		pfree(state.lex);
+		return;
+	}
 
 	/* number of dimensions should be already known */
 	Assert(ctx->ndims > 0 && ctx->dims);
@@ -2750,10 +2778,12 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
 	if (jbv->type != jbvBinary ||
 		!JsonContainerIsArray(jbc) ||
 		JsonContainerIsScalar(jbc))
+	{
 		populate_array_report_expected_array(ctx, ndim - 1);
-
-	if (ctx->error)
+		/* Nothing to do on an error. */
+		Assert(SOFT_ERROR_OCCURRED(ctx->escontext));
 		return;
+	}
 
 	it = JsonbIteratorInit(jbc);
 
@@ -2772,7 +2802,12 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
 		 (tok == WJB_ELEM &&
 		  (val.type != jbvBinary ||
 		   !JsonContainerIsArray(val.val.binary.data)))))
+	{
 		populate_array_assign_ndims(ctx, ndim);
+		/* Nothing to do on an error. */
+		if (SOFT_ERROR_OCCURRED(ctx->escontext))
+			return;
+	}
 
 	jsv.is_json = false;
 	jsv.val.jsonb = &val;
@@ -2790,8 +2825,8 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
 		{
 			/* populate child sub-array */
 			populate_array_dim_jsonb(ctx, &val, ndim + 1);
-
-			if (ctx->error)
+			/* Nothing to do on an error. */
+			if (SOFT_ERROR_OCCURRED(ctx->escontext))
 				return;
 
 			/* number of dimensions should be already known */
@@ -2810,13 +2845,18 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
 	Assert(tok == WJB_DONE && !it);
 }
 
-/* recursively populate an array from json/jsonb */
+/*
+ * Recursively populate an array from json/jsonb
+ *
+ * *isnull is set to if an error is reported during parsing.
+ */
 static Datum
 populate_array(ArrayIOData *aio,
 			   const char *colname,
 			   MemoryContext mcxt,
 			   JsValue *jsv,
-			   Node *escontext)
+			   Node *escontext,
+			   bool *isnull)
 {
 	PopulateArrayContext ctx;
 	Datum		result;
@@ -2832,7 +2872,6 @@ populate_array(ArrayIOData *aio,
 	ctx.dims = NULL;
 	ctx.sizes = NULL;
 	ctx.escontext = escontext;
-	ctx.error = false;
 
 	if (jsv->is_json)
 		populate_array_json(&ctx, jsv->val.json.str,
@@ -2841,13 +2880,17 @@ populate_array(ArrayIOData *aio,
 	else
 	{
 		populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
-		if (!ctx.error)
+		/* Nothing to do on an error. */
+		if (!SOFT_ERROR_OCCURRED(ctx.escontext))
 			ctx.dims[0] = ctx.sizes[0];
 	}
 
-	/* Caller should check SOFT_ERROR_OCCURRED(escontext)! */
-	if (ctx.error)
+	/* Nothing to return if an error occurred. */
+	if (SOFT_ERROR_OCCURRED(ctx.escontext))
+	{
+		*isnull = true;
 		return (Datum) 0;
+	}
 
 	Assert(ctx.ndims > 0);
 
@@ -2863,6 +2906,7 @@ populate_array(ArrayIOData *aio,
 	pfree(ctx.sizes);
 	pfree(lbs);
 
+	*isnull = false;
 	return result;
 }
 
@@ -3224,7 +3268,7 @@ populate_record_field(ColumnIOData *col,
 
 		case TYPECAT_ARRAY:
 			return populate_array(&col->io.array, colname, mcxt, jsv,
-								  escontext);
+								  escontext, isnull);
 
 		case TYPECAT_COMPOSITE:
 		case TYPECAT_COMPOSITE_DOMAIN:
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 3252bcf1ee..5ebafc18d5 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -903,8 +903,8 @@ typedef struct JsonExprState
 	}			input;			/* I/O info for output type */
 
 	/*
-	 * Either of the following two is used by ExecEvalJsonCoercion() to apply
-	 * coercion to the final result if needed.
+	 * Either of the following two is used by ExecEvalJsonExprCoercion() to
+	 * apply coercion to the final result if needed.
 	 */
 	JsonCoercionState *result_jcstate;
 	JsonItemCoercionsState *item_jcstates;
