Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x3JyF-006JkM-1W for pgsql-hackers@arkaria.postgresql.org; Sun, 06 Sep 2026 21:00:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x3JyC-00Ff1n-20 for pgsql-hackers@arkaria.postgresql.org; Sun, 06 Sep 2026 21:00:08 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x3JyC-00Ff1f-0g for pgsql-hackers@lists.postgresql.org; Sun, 06 Sep 2026 21:00:08 +0000 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1x3Jy9-00000003IWy-2H8T for pgsql-hackers@postgresql.org; Sun, 06 Sep 2026 21:00:07 +0000 Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4954a9e8490so20717195e9.1 for ; Sun, 06 Sep 2026 14:00:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788728403; x=1789333203; darn=postgresql.org; h=in-reply-to:from:content-language:references:cc:to:subject :user-agent:mime-version:date:message-id:content-type:from:to:cc :subject:date:message-id:reply-to:content-type; bh=C+xh3uTq15Eh7bCwv2mMwWiMHjIKBywOTIUEQAwp/KQ=; b=SwXRWOKhrLUQpNg9RRkb1ZQo5dEFLrS4Tq7Ix5/eo56BsXp/hRGkm5I1UofiNgLk78 khv3fnqfEUUMrxKOB3P3xiWtD/lpzCABO1/7+OV2x8i5vpUI67i7Inb2ghT2ajmmRgf9 fY56FsCUN61hmhzxLvfezjeUtTDuwpbIcpPD0geQSjGLJFSSymSl0BbS/UlWEoyqIHBr 5Mcmy0IEh21KknQ5mG3jOcZvPptj0CamYh7vWL2NWs2Bdp6AJOKCrwjHASnqFox0v8/Y zQJo9UOENFMl/tTxCIOyBijXKg64oNdYJcbn/KinHGjQacjN0A4aDu1Ka06BRIQOOa2j aVnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788728403; x=1789333203; h=in-reply-to:from:content-language:references:cc:to:subject :user-agent:mime-version:date:message-id:content-type:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=C+xh3uTq15Eh7bCwv2mMwWiMHjIKBywOTIUEQAwp/KQ=; b=rpCXVqBnM6VOimdCZsvAh0mtHgczHNBzZgLY2subUKnNAEuyXjYS4FzxVIPdFvjLHb GEb0K3q2WhSbC2/E1cTfChHUUHDWIOhmOyPQP/D3Sr2nd+kTG9nhhhlIQ4WmZEwI+DZK YAh7D27pKvLF3G73mF0aGNg+UPM4vfJXXjDm5E/JHXuTmk4YFKngSbmoadZDT9uKmOeX I3P3tkE1eoBIpiLJU0TOZ1txb8mcnCe9z2KyFPus/V4RREljOqaWtv9jFQ+ucbMzN/AT qGjBzqooJOALl0TUoNX2433edAQql5dn5B7Bnkf2A+AFFqcBR9LywGQm2ZpHKDE4rOAL hlcQ== X-Forwarded-Encrypted: i=1; AKwUvBxQNe0SWk21UKxUXln/b9t5DRDGDnDwHPPO1ixe789BSMRqnald+LEbzoD9pB0EDOoMZ090+knlgYz9UpAJ@postgresql.org X-Gm-Message-State: AFuF++nIVhqCRrNnC1/vPnZyd1cq/QMSXHQWygnmy6O4Y9hVOYTNz04s VDpmsN45MtZ2/vCw3y9Ga14MrUXNAqXhGFHhp/0l/AOkTGeSn0RwBZJu X-Gm-Gg: AYBFou3nizbxvvJiN1kyDG1bSWAB9GjZPjB5oZUcJYpqkUHqM+X47G+bQnRWonf0NBG l4TWsLnqUl/3Pk8t51sSFEDRmhY+odPOdkoxPRDXWxwrPqOc44a/0v8gh51JStec2TaZTq5pJ6E VD505ZLTePvBF3OmunRxPHUVkhpSzMO41/1ZeCGzOqJ/c2anWNRdF0cDyjU+44CbSP7EyfrYI2u IxSfuVDotooie+g9cTJeyCKWbbMttl/unURufe97RAoZ5MHCbYbwbEZDv3ZeG+yf7VVuzaTWP6R EDTNGvw/avbDEX+Zc7bZnHHyoQ5EFq4IQRvgaw7QJe1pxGGXbeUg1gbD1yY6s5oY09G88BVLax1 3Zkw25snTTFeusMjP2u7IQFLgd8kVN3sGNBH2ScbYnHHuam2xDD2iu+tKwQiSiOypkqfIvYjkda yasDtAVtjmbApBAixQa2DOWRhqS99Lu/Bv3qpdD9LCJOfgH4WYjLTcmsTl43IH+C42AC3eKLh8u Q== X-Received: by 2002:a05:600c:a05:b0:49c:f501:e428 with SMTP id 5b1f17b1804b1-49cf82e5b1amr175746115e9.8.1788728402668; Sun, 06 Sep 2026 14:00:02 -0700 (PDT) Received: from [192.168.0.50] ([89.149.107.253]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49ce58da3acsm737237435e9.0.2026.09.06.14.00.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 06 Sep 2026 14:00:01 -0700 (PDT) Content-Type: multipart/alternative; boundary="------------403bC9dRxpSzyQlyo3rQo8yA" Message-ID: <8343126e-11e5-48df-9f96-ea03a2b7d5ba@gmail.com> Date: Mon, 7 Sep 2026 00:00:00 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Internal error codes triggered by regression tests and user queries, take 2 To: Tom Lane Cc: Michael Paquier , Andres Freund , pgsql-hackers , Justin Pryzby References: <94ac928b-8370-4db5-ada5-579a9ebc089d@gmail.com> <697477.1787754418@sss.pgh.pa.us> <73eb724a-c1a3-456c-be12-0375d4556b67@gmail.com> <91a1b0ab-2c6c-4471-b7a4-ee8ee8aed64e@gmail.com> <126103.1788721678@sss.pgh.pa.us> Content-Language: en-US From: Alexander Lakhin In-Reply-To: <126103.1788721678@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------403bC9dRxpSzyQlyo3rQo8yA Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit 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 --------------403bC9dRxpSzyQlyo3rQo8yA Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
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
--------------403bC9dRxpSzyQlyo3rQo8yA--