diff --git a/pgtype/timestamp.go b/pgtype/timestamp.go
index 89718221..c31f2ac5 100644
--- a/pgtype/timestamp.go
+++ b/pgtype/timestamp.go
@@ -105,19 +105,23 @@ func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	case "-infinity":
 		*ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
 	default:
+		// Parse time with or without timezonr
 		tss := *s
 		//		PostgreSQL uses ISO 8601 without timezone for to_json function and casting from a string to timestampt
-
 		tim, err := time.Parse(time.RFC3339Nano, tss)
 		if err == nil {
 			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
 		}
 		tim, err = time.ParseInLocation(jsonISO8601, tss, time.UTC)
 		if err == nil {
 			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
 		}
+		ts.Valid = false
+		return fmt.Errorf("cannot unmarshal %s to timestamp with layout %s or %s (%w)",
+			*s, time.RFC3339Nano, jsonISO8601, err)
 	}
-
 	return nil
 }
 
diff --git a/pgtype/timestamp_test.go b/pgtype/timestamp_test.go
index bfcdf023..f913c127 100644
--- a/pgtype/timestamp_test.go
+++ b/pgtype/timestamp_test.go
@@ -141,6 +141,18 @@ func TestTimestampMarshalJSON(t *testing.T) {
 	}
 }
 
+func TestTimestampUnmarshalJSONErrors(t *testing.T) {
+	tsStruct := struct {
+		TS pgtype.Timestamp `json:"ts"`
+	}{}
+	goodJson1 := []byte(`{"ts":"2012-03-29T10:05:45"}`)
+	assert.NoError(t, json.Unmarshal(goodJson1, &tsStruct))
+	goodJson2 := []byte(`{"ts":"2012-03-29T10:05:45Z"}`)
+	assert.NoError(t, json.Unmarshal(goodJson2, &tsStruct))
+	badJson := []byte(`{"ts":"2012-03-29"}`)
+	assert.Error(t, json.Unmarshal(badJson, &tsStruct))
+}
+
 func TestTimestampUnmarshalJSON(t *testing.T) {
 	successfulTests := []struct {
 		source string