pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
Internal error codes triggered by regression tests and user queries, take 2
10+ messages / 4 participants
[nested] [flat]

* Internal error codes triggered by regression tests and user queries, take 2
@ 2026-08-26 14:00 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 10+ messages in thread

From: Alexander Lakhin @ 2026-08-26 14:00 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; pgsql-hackers; +Cc: Justin Pryzby <pryzby@telsasoft.com>

Hello Michael,

Please take a look at the follow-up to [0]. I've prepared a patch to
assign error codes for errors reached by the following queries:
1)
create table notnull_tbl_fail (a serial constraint foo not null constraint bar not null); -- from constraints.sql
ERROR:  XX000: conflicting not-null constraint names "foo" and "bar"
LOCATION:  transformColumnDefinition, parse_utilcmd.c:800
     ERRCODE_INVALID_TABLE_DEFINITION

2)
SELECT satisfies_hash_partition(0, 4, 0, NULL); -- from hash_part.sql
ERROR:  XX000: could not open relation with OID 0
LOCATION:  relation_open, relation.c:62
     ERRCODE_INVALID_PARAMETER_VALUE (also modified try_relation_open() for consistency)

3)
SELECT COUNT(*) = 0 AS ok FROM pg_shmem_allocations_numa; -- from numa.sql
ERROR:  XX000: libnuma initialization failed or NUMA is not supported on this platform
LOCATION:  pg_get_shmem_allocations_numa, shmem.c:1122
     ERRCODE_FEATURE_NOT_SUPPORTED

4)
create table idxpart (a int) partition by range (a);
create table idxpart0 (like idxpart);
alter table idxpart0 add unique (a);
alter table idxpart attach partition idxpart0 default;
alter table only idxpart add primary key (a); -- from indexing.sql
ERROR:  XX000: column "a" of table "idxpart0" is not marked NOT NULL
LOCATION:  ATPrepAddPrimaryKey, tablecmds.c:9695
     ERRCODE_INVALID_TABLE_DEFINITION

5)
CREATE FUNCTION test_pglz_compress(bytea)
   RETURNS bytea
   AS '.../src/test/regress/regress.so' LANGUAGE C STRICT;
CREATE FUNCTION test_pglz_decompress(bytea, int4, bool)
   RETURNS bytea
   AS '.../src/test/regress/regress.so' LANGUAGE C STRICT;
SELECT test_pglz_decompress(test_pglz_compress(
         decode(repeat('abcd', 100), 'escape')), 500, true); -- compression_pglz.sql:
ERROR:  XX000: pglz_decompress failed
LOCATION:  test_pglz_decompress, regress.c:1497
     ERRCODE_DATA_CORRUPTED (like for "compressed pglz data is corrupt")

With these changes plus
v1-0001-Report-specific-SQLSTATEs-for-stats-restore-error.patch from [1]
applied,  `make check` passes without XX000 errors for me. Tested with:
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -498,6 +498,7 @@ errfinish(const char *filename, int lineno, const char *funcname)

      elevel = edata->elevel;

+Assert(!(elevel == ERROR && edata->sqlerrcode == ERRCODE_INTERNAL_ERROR));
      /*
       * Do processing in ErrorContext, which we hope has enough reserved space
       * to report an error.

There are also other internal errors produced during `make check-world`,
but I think they should be considered separately, as most of them are too
generic or really internal, like "cache lookup failed for relation xxx"
triggered by intra-grant-inplace.

Besides the above, I've included in the patch assigning error codes to
errors reported by Justin Pryzby at [2], except for the dubious
amvalidate() and pg_read_file with parse_weight (both are already fixed):
6)
select unknownin('');
ERROR:  XX000: failed to find conversion function from unknown to text
LOCATION:  coerce_type, parse_coerce.c:544
     ERRCODE_CANNOT_COERCE (used by other functions in parse_coerce.c)

7)
SELECT pg_catalog.interval( '12 seconds'::interval ,3);
ERROR:  XX000: unrecognized interval typmod: 3
LOCATION:  AdjustIntervalForTypmod, timestamp.c:1492
     ERRCODE_INVALID_PARAMETER_VALUE (like below in the same function)

8)
SELECT pg_describe_object(1,0,1);
ERROR:  XX000: unsupported object class: 1
LOCATION:  getObjectDescription, objectaddress.c:4317
     ERRCODE_WRONG_OBJECT_TYPE

9)
SELECT acldefault('a',0);
ERROR:  XX000: unrecognized object type abbreviation: a
LOCATION:  acldefault_sql, acl.c:999
     ERRCODE_WRONG_OBJECT_TYPE

10)
select float8_regr_intercept(ARRAY[1]);
ERROR:  XX000: float8_regr_intercept: expected 8-element float8 array
LOCATION:  check_float8_array, float.c:2985
     ERRCODE_INVALID_PARAMETER_VALUE

A couple of cases I reported before:
11)
do $$ #print_strict_params XXX $$;
ERROR:  XX000: unrecognized print_strict_params option xxx
CONTEXT:  compilation of PL/pgSQL function "inline_code_block" near line 1
LOCATION:  plpgsql_yyparse, pl_gram.y:396
     ERRCODE_SYNTAX_ERROR

12)
select pg_catalog.range_in('', 23, 0);
ERROR:  XX000: type 23 is not a range type
LOCATION:  get_range_io_data, rangetypes.c:339
     ERRCODE_DATATYPE_MISMATCH (like for "data type %s is not an array type")


[0] https://www.postgresql.org/message-id/aozYob22-UJ8CWzk%40paquier.xyz
[1] https://www.postgresql.org/message-id/CAHGQGwHZLiLa9iM7NAiugp1B7CumN94%3DYBeho9t%3DqKJMnTGwMQ%40mail...
[2] https://www.postgresql.org/message-id/20230213135053.GZ1653%40telsasoft.com

Best regards,
Alexander

Attachments:

  [text/x-patch] define-missing-errcodes.patch (8.0K, ../../94ac928b-8370-4db5-ada5-579a9ebc089d@gmail.com/2-define-missing-errcodes.patch)
  download | inline diff:
diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
index 38b356b8239..ad32bd13d5f 100644
--- a/src/backend/access/common/relation.c
+++ b/src/backend/access/common/relation.c
@@ -59,7 +59,9 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 	r = RelationIdGetRelation(relationId);
 
 	if (!RelationIsValid(r))
-		elog(ERROR, "could not open relation with OID %u", relationId);
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("could not open relation with OID %u", relationId)));
 
 	/*
 	 * If we didn't get the lock ourselves, assert that caller holds one,
@@ -113,7 +115,9 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
 	r = RelationIdGetRelation(relationId);
 
 	if (!RelationIsValid(r))
-		elog(ERROR, "could not open relation with OID %u", relationId);
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("could not open relation with OID %u", relationId)));
 
 	/* If we didn't get the lock ourselves, assert that caller holds one */
 	Assert(lockmode != NoLock ||
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 703754a8123..655eeb1b500 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -4314,7 +4314,10 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
 			}
 
 		default:
-			elog(ERROR, "unsupported object class: %u", object->classId);
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("unsupported object class: %u", object->classId)));
+
 	}
 
 	/* an empty buffer is equivalent to no object found */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9b911310f05..4226115ec84 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9693,6 +9693,7 @@ ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
 				tup = findNotNullConstraint(childrelid, strVal(column));
 				if (!tup)
 					ereport(ERROR,
+							errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 							errmsg("column \"%s\" of table \"%s\" is not marked NOT NULL",
 								   strVal(column), get_rel_name(childrelid)));
 				/* verify it's good enough */
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index d3240f4b265..46e66990ac1 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -541,8 +541,12 @@ coerce_type(ParseState *pstate, Node *node,
 		return (Node *) r;
 	}
 	/* If we get here, caller blew it */
-	elog(ERROR, "failed to find conversion function from %s to %s",
-		 format_type_be(inputTypeId), format_type_be(targetTypeId));
+	ereport(ERROR,
+			(errcode(ERRCODE_CANNOT_COERCE),
+			 errmsg("failed to find conversion function from %s to %s",
+					format_type_be(inputTypeId), format_type_be(targetTypeId))));
+
+
 	return NULL;				/* keep compiler quiet */
 }
 
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 640e1c4f5a4..abfe449f895 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -797,8 +797,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 					if (constraint->conname &&
 						notnull_constraint->conname &&
 						strcmp(notnull_constraint->conname, constraint->conname) != 0)
-						elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
-							 notnull_constraint->conname, constraint->conname);
+						ereport(ERROR,
+								errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+								errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
+									   notnull_constraint->conname, constraint->conname));
 
 					if (notnull_constraint->is_no_inherit != constraint->is_no_inherit)
 						ereport(ERROR,
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 228871d2525..4491aabd9a6 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -1119,7 +1119,9 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	Size	   *nodes;
 
 	if (pg_numa_init() == -1)
-		elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform");
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("libnuma initialization failed or NUMA is not supported on this platform")));
 
 	InitMaterializedSRF(fcinfo, 0);
 
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 25cd5d0296b..2385c1ebbe9 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -996,7 +996,9 @@ acldefault_sql(PG_FUNCTION_ARGS)
 			objtype = OBJECT_TYPE;
 			break;
 		default:
-			elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("unrecognized object type abbreviation: %c", objtypec)));
 	}
 
 	PG_RETURN_ACL_P(acldefault(objtype, owner));
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index fd7a6587132..2a33bc37e81 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -2982,7 +2982,10 @@ check_float8_array(ArrayType *transarray, const char *caller, int n)
 		ARR_DIMS(transarray)[0] != n ||
 		ARR_HASNULL(transarray) ||
 		ARR_ELEMTYPE(transarray) != FLOAT8OID)
-		elog(ERROR, "%s: expected %d-element float8 array", caller, n);
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("%s: expected %d-element float8 array", caller, n)));
+
 	return (float8 *) ARR_DATA_PTR(transarray);
 }
 
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 84d71761c1b..cedfa458c89 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -336,7 +336,9 @@ get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
 												   sizeof(RangeIOData));
 		cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
 		if (cache->typcache->rngelemtype == NULL)
-			elog(ERROR, "type %u is not a range type", rngtypid);
+			ereport(ERROR,
+					(errcode(ERRCODE_DATATYPE_MISMATCH),
+					 errmsg("type %u is not a range type", rngtypid)));
 
 		/* get_type_io_data does more than we need, but is convenient */
 		get_type_io_data(cache->typcache->rngelemtype->type_id,
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 9c17ba2f905..06d238024e5 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1489,7 +1489,10 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
 			/* fractional-second rounding will be dealt with below */
 		}
 		else
-			elog(ERROR, "unrecognized interval typmod: %d", typmod);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized interval typmod: %d", typmod)));
+
 
 		/* Need to adjust sub-second precision? */
 		if (precision != INTERVAL_FULL_PRECISION)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 5e14a2d7302..98410ce6fd6 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -393,7 +393,10 @@ comp_option		: '#' K_OPTION K_DUMP
 						else if (strcmp($3, "off") == 0)
 							plpgsql_curr_compile->print_strict_params = false;
 						else
-							elog(ERROR, "unrecognized print_strict_params option %s", $3);
+							ereport(ERROR,
+									(errcode(ERRCODE_SYNTAX_ERROR),
+									 errmsg("unrecognized print_strict_params option %s", $3)));
+
 					}
 				| '#' K_VARIABLE_CONFLICT K_ERROR
 					{
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index c72ee31cdce..2cd4e17b869 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1494,7 +1494,9 @@ test_pglz_decompress(PG_FUNCTION_ARGS)
 	dlen = pglz_decompress(source, slen, VARDATA(result),
 						   rawsize, check_complete);
 	if (dlen < 0)
-		elog(ERROR, "pglz_decompress failed");
+		ereport(ERROR,
+				(errcode(ERRCODE_DATA_CORRUPTED),
+				 errmsg("pglz_decompress failed")));
 
 	SET_VARSIZE(result, dlen + VARHDRSZ);
 	PG_RETURN_BYTEA_P(result);


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
@ 2026-08-26 14:26 ` Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  0 siblings, 1 reply; 10+ messages in thread

From: Tom Lane @ 2026-08-26 14:26 UTC (permalink / raw)
  To: Alexander Lakhin <exclusion@gmail.com>; +Cc: Michael Paquier <michael@paquier.xyz>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Alexander Lakhin <exclusion@gmail.com> writes:
> Please take a look at the follow-up to [0]. I've prepared a patch to
> assign error codes for errors reached by the following queries:

I'm not on board with these proposed changes to [try_]relation_open.
They're basically band-aids rather than fixes of the root problems.
That is, if someone passes OID 0 to relation_open, that IS an internal
bug; labeling it otherwise is a lie and does nothing to fix the real
problem at the caller level.

A lot of these other proposed changes have the same whiff of blaming
the messenger rather than looking for the root cause.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
@ 2026-08-26 15:17   ` Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  0 siblings, 1 reply; 10+ messages in thread

From: Andres Freund @ 2026-08-26 15:17 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Alexander Lakhin <exclusion@gmail.com>; Michael Paquier <michael@paquier.xyz>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Hi,

On 2026-08-26 10:26:58 -0400, Tom Lane wrote:
> Alexander Lakhin <exclusion@gmail.com> writes:
> > Please take a look at the follow-up to [0]. I've prepared a patch to
> > assign error codes for errors reached by the following queries:
>
> I'm not on board with these proposed changes to [try_]relation_open.
> They're basically band-aids rather than fixes of the root problems.
> That is, if someone passes OID 0 to relation_open, that IS an internal
> bug; labeling it otherwise is a lie and does nothing to fix the real
> problem at the caller level.
>
> A lot of these other proposed changes have the same whiff of blaming
> the messenger rather than looking for the root cause.

+1.

This is triply true for stuff like test_pglz_decompress() - this isn't
something that should be translated or that we care about having a proper
error code assigned.

Most of these would make it *harder* to find unexpected scenarios, i.e. the
patch would make the situation strictly worse. It's useful to be able to
search production logs for internal errors. As-is the patch would break that.

Looking through them, the ones that look relatively clearly to be worth
turning into ereports seem to be:

- pg_get_shmem_allocations_numa() - there's really no reason for this to be an
  elog(), it's obviously expected to be reached on a bunch of platforms / configurations
- transformColumnDefinition() - that's clearly reachable with plain DDL,
  without representing a bug in an upper layer.

I'm a bit on the fence about the one get_range_io_data(). We could catch that
on a higher layer, but
a) that'd be duplicated code,
b) other errors, like not having send/receive are already handled in
   get_range_io_data, with ereports()
c) for e.g. composites, we handle the same problem centrally, rather than have
   checks in record_in() etc (the check is in lookup_rowtype_tupdesc_internal).


Looking at this reminds me of something orthogonal: Isn't it pretty weird that
we have a per-type cache, with lots of information about the types, but don't
have the in/out/send/recv cached in there, but do cache EQ/LT/.. etc?

Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
@ 2026-08-28 12:00     ` Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  0 siblings, 1 reply; 10+ messages in thread

From: Alexander Lakhin @ 2026-08-28 12:00 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Michael Paquier <michael@paquier.xyz>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Hello Andres and Tom,

Thank you for your feedback!

26.08.2026 18:17, Andres Freund wrote:
> On 2026-08-26 10:26:58 -0400, Tom Lane wrote:
>> I'm not on board with these proposed changes to [try_]relation_open.
>> They're basically band-aids rather than fixes of the root problems.
>> That is, if someone passes OID 0 to relation_open, that IS an internal
>> bug; labeling it otherwise is a lie and does nothing to fix the real
>> problem at the caller level.

I agree. The fact that the internal error is reached from a legal SQL-level
function doesn't make all other ways to reach it expected/normal. This is
one issue with this proposal.

The other one is the unclear definition of internal/XX000 errors in
principle. As far as I can see, it varies from "all the errors that have
no specific code assigned" to "critical errors, similar to failed asserts"
(and probably a substitute for asserts in production). And as Andres (and
I too) find it useful to search for XX000 in production logs, it means
they are interpreted per the second definition. In this case, it makes
sense to define missing codes for cases which are not worth paying
attention to in production, e.g. "#print_strict_params XXX". Moreover, if
the second definition (XX000 error ~ failed assert) is going to be
accepted, it seems sensible to have no such errors produced during
regression tests (like no assertion failures).

I remember previous moves in this direction: [1], [2], so I started from
errors produced just by `make check`. I understand that such cases can be
discussed and processed one-by-one (e.g., bug #19659, #19630, #19631,
#19632), but given the number of "elog(ERROR)" in the tree and the number
of known ways to reach them (dozens, I guess), maybe it would be more
efficient to agree on the definition of internal errors and then
categorize all the cases at hand (I thought of creating a wiki page for
that).

>> A lot of these other proposed changes have the same whiff of blaming
>> the messenger rather than looking for the root cause.
> +1.
>
> This is triply true for stuff like test_pglz_decompress() - this isn't
> something that should be translated or that we care about having a proper
> error code assigned.

Yes, and this consideration (we don't care about error code) is closer to
the definition 1, I guess. I proposed the change to align that error with
the similar "compressed pglz data is corrupt", as it doesn't make the
error less scary if we get back to the "search production logs for
critical errors" use case (on the other hand, the error is produced by a
test-only function...).

> Most of these would make it *harder* to find unexpected scenarios, i.e. the
> patch would make the situation strictly worse. It's useful to be able to
> search production logs for internal errors. As-is the patch would break that.

Yes, it would hardly land as-is, but I hope it can help determine ways to
approach these errors in general.

> Looking through them, the ones that look relatively clearly to be worth
> turning into ereports seem to be:
>
> - pg_get_shmem_allocations_numa() - there's really no reason for this to be an
>    elog(), it's obviously expected to be reached on a bunch of platforms / configurations
> - transformColumnDefinition() - that's clearly reachable with plain DDL,
>    without representing a bug in an upper layer.
>
> I'm a bit on the fence about the one get_range_io_data(). We could catch that
> on a higher layer, but
> a) that'd be duplicated code,
> b) other errors, like not having send/receive are already handled in
>     get_range_io_data, with ereports()
> c) for e.g. composites, we handle the same problem centrally, rather than have
>     checks in record_in() etc (the check is in lookup_rowtype_tupdesc_internal).

I would elaborate on these when the consensus on the definition is reached.

[1] https://www.postgresql.org/message-id/flat/ba76c6bc-f03f-4285-bf16-47759cfcab9e%40eisentraut.org
[2] https://www.postgresql.org/message-id/Zic_GNgos5sMxKoa%40paquier.xyz

Best regards,
Alexander

^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
@ 2026-08-31 06:15       ` Michael Paquier <michael@paquier.xyz>
  2026-09-05 08:00         ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  0 siblings, 1 reply; 10+ messages in thread

From: Michael Paquier @ 2026-08-31 06:15 UTC (permalink / raw)
  To: Alexander Lakhin <exclusion@gmail.com>; +Cc: Andres Freund <andres@anarazel.de>; Tom Lane <tgl@sss.pgh.pa.us>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

On Fri, Aug 28, 2026 at 03:00:00PM +0300, Alexander Lakhin wrote:
> I agree. The fact that the internal error is reached from a legal SQL-level
> function doesn't make all other ways to reach it expected/normal. This is
> one issue with this proposal.

Not all of them are.  See below for details.

Looking (finally) at the list you have sent in your patch, I can get
on board for:
- getObjectDescription(), can be queried with a function officially
documented.
- ATPrepAddPrimaryKey().  This one is a bug to me, reachable with SQL.
- transformColumnDefinition().  Also a bug to me.
- pg_get_shmem_allocations_numa.  Bug.
- acldefault() is documented.  Seems worth fixing for correctness,
documented function.
- AdjustIntervalForTypmod().  Documented feature.
- The pl_gram.y one looks like a defect to me by not assigning an
error code.

But not for these:
- relation_open(), incorrect internal state from the caller.
- try_relation_open(), incorrect internal state from the caller.
coerce_type(), also an internal state.  unknownin() is also an
- "internal" input, non-documented SQL function.
- check_float8_array().  Your case involves float8_regr_intercept(),
which is a final aggregate function.  It is not documented, and should
never really be called directly.
- get_range_io_data().  Cannot get excited about this one, either, as
your case involves the direct call of an input function.  Can this
happen with more patterns?
- test_pglz_decompress() is test code, no need to worry about it.

> The other one is the unclear definition of internal/XX000 errors in
> principle. As far as I can see, it varies from "all the errors that have
> no specific code assigned" to "critical errors, similar to failed asserts"
> (and probably a substitute for asserts in production). And as Andres (and
> I too) find it useful to search for XX000 in production logs, it means
> they are interpreted per the second definition. In this case, it makes
> sense to define missing codes for cases which are not worth paying
> attention to in production, e.g. "#print_strict_params XXX". Moreover, if
> the second definition (XX000 error ~ failed assert) is going to be
> accepted, it seems sensible to have no such errors produced during
> regression tests (like no assertion failures).

I think that I would draw a line depending on the documentation.  If
a function is documented as usable, or callable through a view, it
sounds fair to me to assume that a user gets an error code that fits
with the incorrect behavior provided as input argument.  Input
function for types, test code, direct function calls to embedded
facilities like aggregates, or anything like that, not documented, is
not worth bothering.  The fact that none of them is documented is an
argument good enough for me to state that we don't really expect users
to use these this way.

The important piece to keep in mind is that non-internal ereport()
calls mean translation.  There is no point in providing translation
for states that we expect users to never see in the field, and the
docs define what we make user-visible.

> I would elaborate on these when the consensus on the definition is reached.
> 
> [1] https://www.postgresql.org/message-id/flat/ba76c6bc-f03f-4285-bf16-47759cfcab9e%40eisentraut.org
> [2] https://www.postgresql.org/message-id/Zic_GNgos5sMxKoa%40paquier.xyz

Among the 13 patterns you have sent, 7 of them make sense to me as
being reachable through documented patterns, 6 are not.  As far as I
can see, Andres seems to me roughly among the same line, except for
get_range_io_data() that I disagree with as not reachable by normal
(aka documented) means based on the information provided.

Among the 7 patterns worth fixing, I'd suggest either improvements to
the error messages, or even better: check if we could reuse any of the
existing error messages already translated.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../apUcBVyazHEW5pcg@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
@ 2026-09-05 08:00         ` Alexander Lakhin <exclusion@gmail.com>
  2026-09-06 19:07           ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 10+ messages in thread

From: Alexander Lakhin @ 2026-09-05 08:00 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: Andres Freund <andres@anarazel.de>; Tom Lane <tgl@sss.pgh.pa.us>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Hello Michael,

31.08.2026 09:15, Michael Paquier wrote:
> Not all of them are.  See below for details.

Thank you for having a look! Please find v2 patch with 7 approved changes
attached.

> Looking (finally) at the list you have sent in your patch, I can get
> on board for:
> - getObjectDescription(), can be queried with a function officially
> documented.
I kept the message as-is, as it's used in 3 other places, with elog(ERROR), but still...
> - ATPrepAddPrimaryKey().  This one is a bug to me, reachable with SQL.
already translatable
> - transformColumnDefinition().  Also a bug to me.
already translatable, thanks to AddRelationNotNullConstraints(), I
borrowed ERRCODE_SYNTAX_ERROR from it
> - pg_get_shmem_allocations_numa.  Bug.
a unique message, looks good enough to be user-visible
> - acldefault() is documented.  Seems worth fixing for correctness,
> documented function.
the message "unrecognized object type abbreviation: %c" is unique, a
closest one is "unrecognized object type \"%s\"", but I don't find it
suitable here
> - AdjustIntervalForTypmod().  Documented feature.
the message is unique, looks good too
> - The pl_gram.y one looks like a defect to me by not assigning an
> error code.
reused the closest translatable message "unrecognized %s option \"%s\""

> But not for these:
> - relation_open(), incorrect internal state from the caller.
> - try_relation_open(), incorrect internal state from the caller.
> coerce_type(), also an internal state.  unknownin() is also an
> - "internal" input, non-documented SQL function.
> - check_float8_array().  Your case involves float8_regr_intercept(),
> which is a final aggregate function.  It is not documented, and should
> never really be called directly.
> - get_range_io_data().  Cannot get excited about this one, either, as
> your case involves the direct call of an input function.  Can this
> happen with more patterns?
> - test_pglz_decompress() is test code, no need to worry about it.

I agree, let's leave them aside until other (documented) ways to reach
them found.

>> The other one is the unclear definition of internal/XX000 errors in
>> principle. As far as I can see, it varies from "all the errors that have
>> no specific code assigned" to "critical errors, similar to failed asserts"
>> (and probably a substitute for asserts in production). And as Andres (and
>> I too) find it useful to search for XX000 in production logs, it means
>> they are interpreted per the second definition. In this case, it makes
>> sense to define missing codes for cases which are not worth paying
>> attention to in production, e.g. "#print_strict_params XXX". Moreover, if
>> the second definition (XX000 error ~ failed assert) is going to be
>> accepted, it seems sensible to have no such errors produced during
>> regression tests (like no assertion failures).
> I think that I would draw a line depending on the documentation.  If
> a function is documented as usable, or callable through a view, it
> sounds fair to me to assume that a user gets an error code that fits
> with the incorrect behavior provided as input argument.  Input
> function for types, test code, direct function calls to embedded
> facilities like aggregates, or anything like that, not documented, is
> not worth bothering.  The fact that none of them is documented is an
> argument good enough for me to state that we don't really expect users
> to use these this way.
>
> The important piece to keep in mind is that non-internal ereport()
> calls mean translation.  There is no point in providing translation
> for states that we expect users to never see in the field, and the
> docs define what we make user-visible.

Thank you for sharing your point of view! I'll review my collection in
light of it.

Best regards,
Alexander

Attachments:

  [text/x-patch] v2-Define-missing-errcodes.patch (4.3K, ../../91a1b0ab-2c6c-4471-b7a4-ee8ee8aed64e@gmail.com/3-v2-Define-missing-errcodes.patch)
  download | inline diff:
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 703754a8123..cf6f4d866e4 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -4314,7 +4314,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
 			}
 
 		default:
-			elog(ERROR, "unsupported object class: %u", object->classId);
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("unsupported object class: %u", object->classId)));
 	}
 
 	/* an empty buffer is equivalent to no object found */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index fd144d783d9..a3865c02e20 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9631,6 +9631,7 @@ ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
 				tup = findNotNullConstraint(childrelid, strVal(column));
 				if (!tup)
 					ereport(ERROR,
+							errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 							errmsg("column \"%s\" of table \"%s\" is not marked NOT NULL",
 								   strVal(column), get_rel_name(childrelid)));
 				/* verify it's good enough */
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index d83616a8507..360bcbb2cbd 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -794,8 +794,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 					if (constraint->conname &&
 						notnull_constraint->conname &&
 						strcmp(notnull_constraint->conname, constraint->conname) != 0)
-						elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
-							 notnull_constraint->conname, constraint->conname);
+						ereport(ERROR,
+								errcode(ERRCODE_SYNTAX_ERROR),
+								errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
+									   notnull_constraint->conname, constraint->conname));
 
 					if (notnull_constraint->is_no_inherit != constraint->is_no_inherit)
 						ereport(ERROR,
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index f971ee24192..f78c34daee1 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -1210,7 +1210,9 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	Size	   *nodes;
 
 	if (pg_numa_init() == -1)
-		elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform");
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("libnuma initialization failed or NUMA is not supported on this platform")));
 
 	InitMaterializedSRF(fcinfo, 0);
 
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 25cd5d0296b..2385c1ebbe9 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -996,7 +996,9 @@ acldefault_sql(PG_FUNCTION_ARGS)
 			objtype = OBJECT_TYPE;
 			break;
 		default:
-			elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("unrecognized object type abbreviation: %c", objtypec)));
 	}
 
 	PG_RETURN_ACL_P(acldefault(objtype, owner));
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 9c17ba2f905..ab86a03280e 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1489,7 +1489,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
 			/* fractional-second rounding will be dealt with below */
 		}
 		else
-			elog(ERROR, "unrecognized interval typmod: %d", typmod);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized interval typmod: %d", typmod)));
 
 		/* Need to adjust sub-second precision? */
 		if (precision != INTERVAL_FULL_PRECISION)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 5e14a2d7302..37785f58cc2 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -393,7 +393,9 @@ comp_option		: '#' K_OPTION K_DUMP
 						else if (strcmp($3, "off") == 0)
 							plpgsql_curr_compile->print_strict_params = false;
 						else
-							elog(ERROR, "unrecognized print_strict_params option %s", $3);
+							ereport(ERROR,
+									(errcode(ERRCODE_SYNTAX_ERROR),
+									 errmsg("unrecognized %s option \"%s\"", "print_strict_params", $3)));
 					}
 				| '#' K_VARIABLE_CONFLICT K_ERROR
 					{


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  2026-09-05 08:00         ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
@ 2026-09-06 19:07           ` Tom Lane <tgl@sss.pgh.pa.us>
  2026-09-06 21:00             ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  0 siblings, 1 reply; 10+ messages in thread

From: Tom Lane @ 2026-09-06 19:07 UTC (permalink / raw)
  To: Alexander Lakhin <exclusion@gmail.com>; +Cc: Michael Paquier <michael@paquier.xyz>; Andres Freund <andres@anarazel.de>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Alexander Lakhin <exclusion@gmail.com> writes:
> Thank you for having a look! Please find v2 patch with 7 approved changes
> attached.

Thanks for working on this cleanup, but I have a few quibbles:

@@ -4314,7 +4314,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
             }
 
         default:
-            elog(ERROR, "unsupported object class: %u", object->classId);
+            ereport(ERROR,
+                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                     errmsg("unsupported object class: %u", object->classId)));
     }

I think we mostly use ERRCODE_WRONG_OBJECT_TYPE for cases where a SQL
object exists but is the wrong kind for the command (eg, a table for
a command that operates on indexes).  Here that's not the case;
there cannot be any relevant object.  The only access path that
I know of is something like

regression=# select pg_describe_object(34,56,0);
ERROR:  unsupported object class: 34

so I'd be kind of inclined to use ERRCODE_INVALID_PARAMETER_VALUE.


@@ -794,8 +794,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
                     if (constraint->conname &&
                         notnull_constraint->conname &&
                         strcmp(notnull_constraint->conname, constraint->conname) != 0)
-                        elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
-                             notnull_constraint->conname, constraint->conname);
+                        ereport(ERROR,
+                                errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
+                                       notnull_constraint->conname, constraint->conname));

This does not seem like a "syntax error".  Perhaps
ERRCODE_INVALID_OBJECT_DEFINITION would serve?


@@ -996,7 +996,9 @@ acldefault_sql(PG_FUNCTION_ARGS)
             objtype = OBJECT_TYPE;
             break;
         default:
-            elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
+            ereport(ERROR,
+                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                     errmsg("unrecognized object type abbreviation: %c", objtypec)));
     }

As above, I think ERRCODE_INVALID_PARAMETER_VALUE is better suited.
Also, if we're going to take this seriously as a reachable error,
we need to protect against producing invalidly-encoded output
in case objtypec has the high bit set (compare ce6bf3cd1).


@@ -1489,7 +1489,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
             /* fractional-second rounding will be dealt with below */
         }
         else
-            elog(ERROR, "unrecognized interval typmod: %d", typmod);
+            ereport(ERROR,
+                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                     errmsg("unrecognized interval typmod: %d", typmod)));

Hmm, is this actually a user-reachable case?  The place that I think
is reachable is over here:

regression=# select format_type('interval'::regtype, 52);
ERROR:  invalid INTERVAL typmod: 0x34
regression=# \errverbose 
ERROR:  XX000: invalid INTERVAL typmod: 0x34
LOCATION:  intervaltypmodout, timestamp.c:1189

We'd be well advised to make those two messages more consistent,
whether they're worth translating or not.  Also I guess a sweep
for other "unreachable" errors in typmodout functions might be
useful.


@@ -393,7 +393,9 @@ comp_option        : '#' K_OPTION K_DUMP
                         else if (strcmp($3, "off") == 0)
                             plpgsql_curr_compile->print_strict_params = false;
                         else
-                            elog(ERROR, "unrecognized print_strict_params option %s", $3);
+                            ereport(ERROR,
+                                    (errcode(ERRCODE_SYNTAX_ERROR),
+                                     errmsg("unrecognized %s option \"%s\"", "print_strict_params", $3)));
                     }
                 | '#' K_VARIABLE_CONFLICT K_ERROR
                     {

There's an argument for ERRCODE_INVALID_PARAMETER_VALUE here too,
perhaps.  But I see that all the other uses of this errmsg string
use ERRCODE_SYNTAX_ERROR, so maybe it's fine as you have it.

			regards, tom lane






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  2026-09-05 08:00         ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-09-06 19:07           ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
@ 2026-09-06 21:00             ` Alexander Lakhin <exclusion@gmail.com>
  2026-09-12 11:00               ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  0 siblings, 1 reply; 10+ messages in thread

From: Alexander Lakhin @ 2026-09-06 21:00 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Michael Paquier <michael@paquier.xyz>; Andres Freund <andres@anarazel.de>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Hello Tom,

06.09.2026 22:07, Tom Lane wrote:
> Thanks for working on this cleanup, but I have a few quibbles:
>
> @@ -4314,7 +4314,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
>               }
>   
>           default:
> -            elog(ERROR, "unsupported object class: %u", object->classId);
> +            ereport(ERROR,
> +                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> +                     errmsg("unsupported object class: %u", object->classId)));
>       }
>
> I think we mostly use ERRCODE_WRONG_OBJECT_TYPE for cases where a SQL
> object exists but is the wrong kind for the command (eg, a table for
> a command that operates on indexes).  Here that's not the case;
> there cannot be any relevant object.  The only access path that
> I know of is something like
>
> regression=# select pg_describe_object(34,56,0);
> ERROR:  unsupported object class: 34
>
> so I'd be kind of inclined to use ERRCODE_INVALID_PARAMETER_VALUE.

Thank you for the clarification! Will change this way.

> @@ -794,8 +794,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
>                       if (constraint->conname &&
>                           notnull_constraint->conname &&
>                           strcmp(notnull_constraint->conname, constraint->conname) != 0)
> -                        elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
> -                             notnull_constraint->conname, constraint->conname);
> +                        ereport(ERROR,
> +                                errcode(ERRCODE_SYNTAX_ERROR),
> +                                errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
> +                                       notnull_constraint->conname, constraint->conname));
>
> This does not seem like a "syntax error".  Perhaps
> ERRCODE_INVALID_OBJECT_DEFINITION would serve?

Yeah, I considered this, but the same errmsg in
AddRelationNotNullConstraints() uses ERRCODE_SYNTAX_ERROR. I found it
more consistent to emit the same code. Maybe it would make do the opposite
-- change the errcode in AddRelationNotNullConstraints() (there are two
instances there, though)... Moreover, ERRCODE_SYNTAX_ERROR is chosen for
many other similar messages in transformColumnDefinition(), so I'm not
sure if it makes sense to change all of those or just report "syntax error"
for consistency while keeping the patch focused.

> @@ -996,7 +996,9 @@ acldefault_sql(PG_FUNCTION_ARGS)
>               objtype = OBJECT_TYPE;
>               break;
>           default:
> -            elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
> +            ereport(ERROR,
> +                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> +                     errmsg("unrecognized object type abbreviation: %c", objtypec)));
>       }
>
> As above, I think ERRCODE_INVALID_PARAMETER_VALUE is better suited.
> Also, if we're going to take this seriously as a reachable error,
> we need to protect against producing invalidly-encoded output
> in case objtypec has the high bit set (compare ce6bf3cd1).

Thank you for the suggestion! Will change the code and add the protection.

> @@ -1489,7 +1489,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
>               /* fractional-second rounding will be dealt with below */
>           }
>           else
> -            elog(ERROR, "unrecognized interval typmod: %d", typmod);
> +            ereport(ERROR,
> +                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> +                     errmsg("unrecognized interval typmod: %d", typmod)));
>
> Hmm, is this actually a user-reachable case?  The place that I think
> is reachable is over here:
>
> regression=# select format_type('interval'::regtype, 52);
> ERROR:  invalid INTERVAL typmod: 0x34
> regression=# \errverbose
> ERROR:  XX000: invalid INTERVAL typmod: 0x34
> LOCATION:  intervaltypmodout, timestamp.c:1189

Yeah, I have this one in my collection too, but started from internal
errors reported previously -- that one at [1], it is reachable with,
e.g.:
SELECT pg_catalog.interval('1 second', 0);
ERROR:  XX000: unrecognized interval typmod: 0
LOCATION:  AdjustIntervalForTypmod, timestamp.c:1492

> We'd be well advised to make those two messages more consistent,
> whether they're worth translating or not.  Also I guess a sweep
> for other "unreachable" errors in typmodout functions might be
> useful.

Will check them and include into this patch.

> @@ -393,7 +393,9 @@ comp_option        : '#' K_OPTION K_DUMP
>                           else if (strcmp($3, "off") == 0)
>                               plpgsql_curr_compile->print_strict_params = false;
>                           else
> -                            elog(ERROR, "unrecognized print_strict_params option %s", $3);
> +                            ereport(ERROR,
> +                                    (errcode(ERRCODE_SYNTAX_ERROR),
> +                                     errmsg("unrecognized %s option \"%s\"", "print_strict_params", $3)));
>                       }
>                   | '#' K_VARIABLE_CONFLICT K_ERROR
>                       {
>
> There's an argument for ERRCODE_INVALID_PARAMETER_VALUE here too,
> perhaps.  But I see that all the other uses of this errmsg string
> use ERRCODE_SYNTAX_ERROR, so maybe it's fine as you have it.

Yes, I'm not aware of cases where one errmsg is issued with different
codes (probably there may be such cases with very generic messages), but
I'd stick to reusing existing code if it's not too wrong.

[1] https://www.postgresql.org/message-id/20230213135053.GZ1653@telsasoft.com

Best regards,
Alexander

^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  2026-09-05 08:00         ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-09-06 19:07           ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-09-06 21:00             ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
@ 2026-09-12 11:00               ` Alexander Lakhin <exclusion@gmail.com>
  2026-09-22 10:49                 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  0 siblings, 1 reply; 10+ messages in thread

From: Alexander Lakhin @ 2026-09-12 11:00 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Michael Paquier <michael@paquier.xyz>; Andres Freund <andres@anarazel.de>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

Hello Tom,

07.09.2026 00:00, Alexander Lakhin wrote:
>
> 06.09.2026 22:07, Tom Lane wrote:
>
>> @@ -794,8 +794,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
>>                       if (constraint->conname &&
>>                           notnull_constraint->conname &&
>>                           strcmp(notnull_constraint->conname, constraint->conname) != 0)
>> -                        elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
>> -                             notnull_constraint->conname, constraint->conname);
>> +                        ereport(ERROR,
>> +                                errcode(ERRCODE_SYNTAX_ERROR),
>> +                                errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
>> +                                       notnull_constraint->conname, constraint->conname));
>>
>> This does not seem like a "syntax error".  Perhaps
>> ERRCODE_INVALID_OBJECT_DEFINITION would serve?
>
> Yeah, I considered this, but the same errmsg in
> AddRelationNotNullConstraints() uses ERRCODE_SYNTAX_ERROR. I found it
> more consistent to emit the same code. Maybe it would make do the opposite
> -- change the errcode in AddRelationNotNullConstraints() (there are two
> instances there, though)... Moreover, ERRCODE_SYNTAX_ERROR is chosen for
> many other similar messages in transformColumnDefinition(), so I'm not
> sure if it makes sense to change all of those or just report "syntax error"
> for consistency while keeping the patch focused.

I've changed that occurrence to ERRCODE_INVALID_OBJECT_DEFINITION, but as
I mentioned above, transformColumnDefinition() has many other SYNTAX_ERRORs
(originating from a56ff9a0b), besides AddRelationNotNullConstraints().
Please find attached a patch to correct these too, for consistency, if you
find this appropriate. There are other similar errors in parse_utilcmd.c,
but I'd stop here unless we want to start a new campaign not to define,
but correct error codes according to some convention.

>> We'd be well advised to make those two messages more consistent,
>> whether they're worth translating or not.  Also I guess a sweep
>> for other "unreachable" errors in typmodout functions might be
>> useful

Changed three occurrences to use the same errmsg and errcode.

Please look at the attached v3-Define-...patch, where I think I addressed
all of your comments.

Thank you for your time!

Best regards,
Alexander

Attachments:

  [text/x-patch] v3-Define-missing-errcodes.patch (5.4K, ../../7a9b3652-134c-4565-82ad-839035a3a382@gmail.com/2-v3-Define-missing-errcodes.patch)
  download | inline diff:
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index b08e076e65f..c1b2e84146b 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -4064,7 +4064,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
 			}
 
 		default:
-			elog(ERROR, "unsupported object class: %u", object->classId);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unsupported object class: %u", object->classId)));
 	}
 
 	/* an empty buffer is equivalent to no object found */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 8dc70bfa0f1..5a2c9f02bf6 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9621,6 +9621,7 @@ ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
 				tup = findNotNullConstraint(childrelid, strVal(column));
 				if (!tup)
 					ereport(ERROR,
+							errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 							errmsg("column \"%s\" of table \"%s\" is not marked NOT NULL",
 								   strVal(column), get_rel_name(childrelid)));
 				/* verify it's good enough */
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index f838311090b..f0c7755b8fb 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -805,8 +805,10 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 					if (constraint->conname &&
 						notnull_constraint->conname &&
 						strcmp(notnull_constraint->conname, constraint->conname) != 0)
-						elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"",
-							 notnull_constraint->conname, constraint->conname);
+						ereport(ERROR,
+								errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+								errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
+									   notnull_constraint->conname, constraint->conname));
 
 					if (notnull_constraint->is_no_inherit != constraint->is_no_inherit)
 						ereport(ERROR,
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index f971ee24192..f78c34daee1 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -1210,7 +1210,9 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	Size	   *nodes;
 
 	if (pg_numa_init() == -1)
-		elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform");
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("libnuma initialization failed or NUMA is not supported on this platform")));
 
 	InitMaterializedSRF(fcinfo, 0);
 
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index a01d8f4bc41..913d715a8c8 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -989,7 +989,16 @@ acldefault_sql(PG_FUNCTION_ARGS)
 			objtype = OBJECT_TYPE;
 			break;
 		default:
-			elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
+			/* Avoid printing non-ASCII bytes, else we have encoding issues */
+			if (objtypec >= ' ' && objtypec < 0x7f)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("unrecognized object type abbreviation: \"%c\"", objtypec)));
+			else				/* use \ooo format, like charout() */
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("unrecognized object type abbreviation: \"\\%03o\"",
+								(unsigned char) objtypec)));
 	}
 
 	PG_RETURN_ACL_P(acldefault(objtype, owner));
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 8ef16c9ad4c..43efa548452 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1186,7 +1186,9 @@ intervaltypmodout(PG_FUNCTION_ARGS)
 			fieldstr = "";
 			break;
 		default:
-			elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized interval typmod: %d", typmod)));
 			fieldstr = "";
 			break;
 	}
@@ -1246,7 +1248,9 @@ intervaltypmodleastfield(int32 typmod)
 		case INTERVAL_FULL_RANGE:
 			return 0;			/* SECOND */
 		default:
-			elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized interval typmod: %d", typmod)));
 			break;
 	}
 	return 0;					/* can't get here, but keep compiler quiet */
@@ -1489,7 +1493,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
 			/* fractional-second rounding will be dealt with below */
 		}
 		else
-			elog(ERROR, "unrecognized interval typmod: %d", typmod);
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized interval typmod: %d", typmod)));
 
 		/* Need to adjust sub-second precision? */
 		if (precision != INTERVAL_FULL_PRECISION)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 5e14a2d7302..37785f58cc2 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -393,7 +393,9 @@ comp_option		: '#' K_OPTION K_DUMP
 						else if (strcmp($3, "off") == 0)
 							plpgsql_curr_compile->print_strict_params = false;
 						else
-							elog(ERROR, "unrecognized print_strict_params option %s", $3);
+							ereport(ERROR,
+									(errcode(ERRCODE_SYNTAX_ERROR),
+									 errmsg("unrecognized %s option \"%s\"", "print_strict_params", $3)));
 					}
 				| '#' K_VARIABLE_CONFLICT K_ERROR
 					{


  [text/x-patch] v3-Correct-errcodes-in-transformColumnDefinition-AddRelationNotNullConstraints.patch (6.3K, ../../7a9b3652-134c-4565-82ad-839035a3a382@gmail.com/3-v3-Correct-errcodes-in-transformColumnDefinition-AddRelationNotNullConstraints.patch)
  download | inline diff:
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 1c188b7a0ff..f7fa1b901d1 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3001,7 +3001,7 @@ AddRelationNotNullConstraints(Relation rel, List *constraints,
 			{
 				if (other->is_no_inherit != constr->is_no_inherit)
 					ereport(ERROR,
-							errcode(ERRCODE_SYNTAX_ERROR),
+							errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							errmsg("conflicting NO INHERIT declaration for not-null constraint on column \"%s\"",
 								   strVal(linitial(constr->keys))));
 
@@ -3015,7 +3015,7 @@ AddRelationNotNullConstraints(Relation rel, List *constraints,
 						constr->conname = pstrdup(other->conname);
 					else if (strcmp(constr->conname, other->conname) != 0)
 						ereport(ERROR,
-								errcode(ERRCODE_SYNTAX_ERROR),
+								errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 								errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
 									   constr->conname, other->conname));
 				}
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index f0c7755b8fb..0210b568a1e 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -749,7 +749,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 			case CONSTR_NULL:
 				if ((saw_nullable && column->is_not_null) || need_notnull)
 					ereport(ERROR,
-							(errcode(ERRCODE_SYNTAX_ERROR),
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
 									column->colname, cxt->relation->relname),
 							 parser_errposition(cxt->pstate,
@@ -767,7 +767,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 				/* Disallow conflicting [NOT] NULL markings */
 				if (saw_nullable && !column->is_not_null)
 					ereport(ERROR,
-							(errcode(ERRCODE_SYNTAX_ERROR),
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
 									column->colname, cxt->relation->relname),
 							 parser_errposition(cxt->pstate,
@@ -775,7 +775,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 				if (disallow_noinherit_notnull && constraint->is_no_inherit)
 					ereport(ERROR,
-							errcode(ERRCODE_SYNTAX_ERROR),
+							errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							errmsg("conflicting NO INHERIT declarations for not-null constraints on column \"%s\"",
 								   column->colname));
 
@@ -812,7 +812,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 					if (notnull_constraint->is_no_inherit != constraint->is_no_inherit)
 						ereport(ERROR,
-								errcode(ERRCODE_SYNTAX_ERROR),
+								errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 								errmsg("conflicting NO INHERIT declarations for not-null constraints on column \"%s\"",
 									   column->colname));
 
@@ -825,7 +825,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 			case CONSTR_DEFAULT:
 				if (saw_default)
 					ereport(ERROR,
-							(errcode(ERRCODE_SYNTAX_ERROR),
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							 errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
 									column->colname, cxt->relation->relname),
 							 parser_errposition(cxt->pstate,
@@ -855,7 +855,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 					if (saw_identity)
 						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
+								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 								 errmsg("multiple identity specifications for column \"%s\" of table \"%s\"",
 										column->colname, cxt->relation->relname),
 								 parser_errposition(cxt->pstate,
@@ -877,7 +877,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 						need_notnull = true;
 					else if (!column->is_not_null)
 						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
+								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 								 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
 										column->colname, cxt->relation->relname),
 								 parser_errposition(cxt->pstate,
@@ -892,7 +892,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 							 errmsg("generated columns are not supported on typed tables")));
 				if (saw_generated)
 					ereport(ERROR,
-							(errcode(ERRCODE_SYNTAX_ERROR),
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							 errmsg("multiple generation clauses specified for column \"%s\" of table \"%s\"",
 									column->colname, cxt->relation->relname),
 							 parser_errposition(cxt->pstate,
@@ -910,7 +910,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 			case CONSTR_PRIMARY:
 				if (saw_nullable && !column->is_not_null)
 					ereport(ERROR,
-							(errcode(ERRCODE_SYNTAX_ERROR),
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
 									column->colname, cxt->relation->relname),
 							 parser_errposition(cxt->pstate,
@@ -975,7 +975,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 		if (saw_default && saw_identity)
 			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					 errmsg("both default and identity specified for column \"%s\" of table \"%s\"",
 							column->colname, cxt->relation->relname),
 					 parser_errposition(cxt->pstate,
@@ -983,7 +983,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 		if (saw_default && saw_generated)
 			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					 errmsg("both default and generation expression specified for column \"%s\" of table \"%s\"",
 							column->colname, cxt->relation->relname),
 					 parser_errposition(cxt->pstate,
@@ -991,7 +991,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 
 		if (saw_identity && saw_generated)
 			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					 errmsg("both identity and generation expression specified for column \"%s\" of table \"%s\"",
 							column->colname, cxt->relation->relname),
 					 parser_errposition(cxt->pstate,


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Internal error codes triggered by regression tests and user queries, take 2
  2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-26 14:26 ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-08-26 15:17   ` Re: Internal error codes triggered by regression tests and user queries, take 2 Andres Freund <andres@anarazel.de>
  2026-08-28 12:00     ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-08-31 06:15       ` Re: Internal error codes triggered by regression tests and user queries, take 2 Michael Paquier <michael@paquier.xyz>
  2026-09-05 08:00         ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-09-06 19:07           ` Re: Internal error codes triggered by regression tests and user queries, take 2 Tom Lane <tgl@sss.pgh.pa.us>
  2026-09-06 21:00             ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
  2026-09-12 11:00               ` Re: Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
@ 2026-09-22 10:49                 ` Michael Paquier <michael@paquier.xyz>
  0 siblings, 0 replies; 10+ messages in thread

From: Michael Paquier @ 2026-09-22 10:49 UTC (permalink / raw)
  To: Alexander Lakhin <exclusion@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Andres Freund <andres@anarazel.de>; pgsql-hackers; Justin Pryzby <pryzby@telsasoft.com>

On Sat, Sep 12, 2026 at 02:00:00PM +0300, Alexander Lakhin wrote:
> Please look at the attached v3-Define-...patch, where I think I addressed
> all of your comments.

The ACL bits were slightly puzzling because it's the first time I see
this pattern in the code (following Tom's comment upthread also in
tsvector), and I indeed get much better error messages:
=# SELECT acldefault(E'\x80'::"char", 0);
ERROR:  22021: invalid byte sequence for encoding "UTF8": 0x80
=# SELECT acldefault(chr(1)::"char", 10);
ERROR:  22023: unrecognized object type abbreviation: "\001"

The second query just showed nothing originally.

For the typmods, %d is a better choice to me as the input is an
integer.

As a whole, that looks OK, so applied on HEAD.  I did not look at
0002.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../arJdH4WF14EXwWmt@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 10+ messages in thread


end of thread, other threads:[~2026-09-22 10:49 UTC | newest]

Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-08-26 14:00 Internal error codes triggered by regression tests and user queries, take 2 Alexander Lakhin <exclusion@gmail.com>
2026-08-26 14:26 ` Tom Lane <tgl@sss.pgh.pa.us>
2026-08-26 15:17   ` Andres Freund <andres@anarazel.de>
2026-08-28 12:00     ` Alexander Lakhin <exclusion@gmail.com>
2026-08-31 06:15       ` Michael Paquier <michael@paquier.xyz>
2026-09-05 08:00         ` Alexander Lakhin <exclusion@gmail.com>
2026-09-06 19:07           ` Tom Lane <tgl@sss.pgh.pa.us>
2026-09-06 21:00             ` Alexander Lakhin <exclusion@gmail.com>
2026-09-12 11:00               ` Alexander Lakhin <exclusion@gmail.com>
2026-09-22 10:49                 ` Michael Paquier <michael@paquier.xyz>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox