BUG #19028: INITDB fails post-bootstrap initialization with FATAL " " is not a valid binary digit at character 1 - Mailing list pgsql-bugs

From PG Bug reporting form
Subject BUG #19028: INITDB fails post-bootstrap initialization with FATAL " " is not a valid binary digit at character 1
Date
Msg-id 19028-d6dfc9c7b3225295@postgresql.org
Whole thread Raw
List pgsql-bugs
The following bug has been logged on the website:

Bug reference:      19028
Logged by:          Ayoub Kazar
Email address:      ma_kazar@esi.dz
PostgreSQL version: 18beta3
Operating system:   Ubuntu 22.04.4 LTS
Description:

Hi everyone,

This is from current master branch, compiled with ./configure
--prefix=/home/ayoubkaz/pg_new_master --enable-debug CFLAGS='-O2 -g'
Error from INITDB:
postgres git:(master) ✗ /home/ayoubkaz/pg_new_master/bin/initdb -D
/home/ayoubkaz/pg_new_master_data
The files belonging to this database system will be owned by user
"ayoubkaz".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are enabled.

creating directory /home/ayoubkaz/pg_new_master_data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 100
selecting default "shared_buffers" ... 128MB
selecting default time zone ... Africa/Algiers
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... 2025-08-21 03:43:47.341 CET
[199047] FATAL:  " " is not a valid binary digit at character 1670
2025-08-21 03:43:47.341 CET [199047] STATEMENT:

        /*
         * PostgreSQL System Functions
         *
         * Copyright (c) 1996-2025, PostgreSQL Global Development Group
         *
         * src/backend/catalog/system_functions.sql
         *
         * This file redefines certain built-in functions that are
impractical
         * to fully define in pg_proc.dat.  In most cases that's because
they use
         * SQL-standard function bodies and/or default expressions.  The
node
         * tree representations of those are too unreadable,
platform-dependent,
         * and changeable to want to deal with them manually.  Hence, we put
stub
         * definitions of such functions into pg_proc.dat and then replace
them
         * here.  The stub definitions would be unnecessary were it not that
we'd
         * like these functions to have stable OIDs, the same as other
built-in
         * functions.
         *
         * This file also takes care of adjusting privileges for those
functions
         * that should not have the default public-EXECUTE privileges.
(However,
         * a small number of functions that exist mainly to underlie system
views
         * are dealt with in system_views.sql, instead.)
         *
         * Note: this file is read in single-user -j mode, which means that
the
         * command terminator is semicolon-newline-newline; whenever the
backend
         * sees that, it stops and executes what it's got.  If you write a
lot of
         * statements without empty lines between, they'll all get quoted to
you
         * in any error message about one of them, so don't do that.  Also,
you
         * cannot write a semicolon immediately followed by an empty line in
a
         * string literal (including a function body!) or a multiline
comment.
         */


        CREATE OR REPLACE FUNCTION lpad(text, integer)
         RETURNS text
         LANGUAGE sql
         IMMUTABLE PARALLEL SAFE STRICT COST 1
        RETURN lpad($1, $2, ' ');

child process exited with exit code 1
initdb: removing data directory "/home/ayoubkaz/pg_new_master_data"

Initdb runs post-bootstrap initialization sql files like constraints,
functions and views .... using a cmd piped postgres backend in single mode.
Currently it fails at system functions initialization "setup_run_file(cmdfd,
system_functions_file);"

After checking with actual sql files and perl script generating system
constraints file just to make sure they all follow the rules of
initialization, they look good.

Using gdb we can see the moment where it fails at setup_run_file with a
SIGPIPE

1732            for (char **line = lines; *line != NULL; line++)
(gdb) p *line
$2 = 0x5555555a6960 "RETURN lpad($1, $2, ' ');\n"
(gdb) n
1734                    PG_CMD_PUTS(*line);
(gdb)
1735                    free(*line);
(gdb)
1732            for (char **line = lines; *line != NULL; line++)
(gdb)
1734                    PG_CMD_PUTS(*line);
(gdb) p *line
$4 = 0x5555555a54a0 "\n"
(gdb) print *cmdfd
$5 = {_flags = -72536956,
  _IO_read_ptr = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_read_end = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_read_base = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_write_base = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_write_ptr = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_write_end = 0x5555555afeb0 " _null_ 1",
  _IO_buf_base = 0x5555555aeeb0 "RETURN lpad($1, $2, ' ');\nTRICT COST
1\nnteger)\nor a multiline
comment.\n\n\n\nn_rel_srrelid_srsubid_index;\ndex;\noint_left _null_ _null_
_null_ _null\240",
  _IO_buf_end = 0x5555555afeb0 " _null_ 1", _IO_save_base = 0x0,
_IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain =
0x7ffff7c1b6a0 <_IO_2_1_stderr_>, _fileno = 4, _flags2 = 0,
  _old_offset = 8010900073819696940, _cur_column = 0, _vtable_offset = 32 '
', _shortbuf = "'", _lock = 0x5555555a5940, _offset = -1, _codecvt =
0x63612c657a69732c, _wide_data = 0xffffffffffffffff,
  _freeres_list = 0x0, _freeres_buf = 0x65676e6168632c6e, __pad5 =
8028075772427264812, _mode = -1, _unused2 = "dir}' _null_ _null_ "}
(gdb) n
2025-08-21 04:00:09.272 CET [200703] FATAL:  " " is not a valid binary digit
at character 1670
2025-08-21 04:00:09.272 CET [200703] STATEMENT:

        /*
         * PostgreSQL System Functions
         *
         * Copyright (c) 1996-2025, PostgreSQL Global Development Group
         *
         * src/backend/catalog/system_functions.sql
         *
         * This file redefines certain built-in functions that are
impractical
         * to fully define in pg_proc.dat.  In most cases that's because
they use
         * SQL-standard function bodies and/or default expressions.  The
node
         * tree representations of those are too unreadable,
platform-dependent,
         * and changeable to want to deal with them manually.  Hence, we put
stub
         * definitions of such functions into pg_proc.dat and then replace
them
         * here.  The stub definitions would be unnecessary were it not that
we'd
         * like these functions to have stable OIDs, the same as other
built-in
         * functions.
         *
         * This file also takes care of adjusting privileges for those
functions
         * that should not have the default public-EXECUTE privileges.
(However,
         * a small number of functions that exist mainly to underlie system
views
         * are dealt with in system_views.sql, instead.)
         *
         * Note: this file is read in single-user -j mode, which means that
the
         * command terminator is semicolon-newline-newline; whenever the
backend
         * sees that, it stops and executes what it's got.  If you write a
lot of
         * statements without empty lines between, they'll all get quoted to
you
         * in any error message about one of them, so don't do that.  Also,
you
         * cannot write a semicolon immediately followed by an empty line in
a
         * string literal (including a function body!) or a multiline
comment.
         */


        CREATE OR REPLACE FUNCTION lpad(text, integer)
         RETURNS text
         LANGUAGE sql
         IMMUTABLE PARALLEL SAFE STRICT COST 1
        RETURN lpad($1, $2, ' ');

1735                    free(*line);
(gdb) n
1732            for (char **line = lines; *line != NULL; line++)
(gdb)
1734                    PG_CMD_PUTS(*line);
(gdb)

Program received signal SIGPIPE, Broken pipe.
0x00007ffff7b14887 in __GI___libc_write (fd=4, buf=0x5555555aeeb0,
nbytes=47) at ../sysdeps/unix/sysv/linux/write.c:26
26      ../sysdeps/unix/sysv/linux/write.c: No such file or directory.
(gdb)

This happens right at PG_CMD_PUTS('\n') this is the second expected newline
after a command (here it's the first command in system_functions)

Went down with gdb for postgres process, and indeed i reach this
transformExprRecurse (pstate=0x5555560b14a0, expr=0x55555613f9f8) at
parse_expr.c:137
137     {
(gdb) n
140             if (expr == NULL)
(gdb)
144             check_stack_depth();
(gdb)
146             switch (nodeTag(expr))
(gdb)
157                             result = (Node *) make_const(pstate,
(A_Const *) expr);
(gdb) step
make_const (pstate=0x5555560b14a0, aconst=0x55555613f9f8) at
parse_node.c:348
348     {
(gdb) n
356             if (aconst->isnull)
(gdb)
370             switch (nodeTag(&aconst->val))
(gdb)
454                             setup_parser_errposition_callback(&pcbstate,
pstate, aconst->location);
(gdb)
144             pcbstate->pstate = pstate;
(gdb)
454                             setup_parser_errposition_callback(&pcbstate,
pstate, aconst->location);
(gdb)
145             pcbstate->location = location;
(gdb)
454                             setup_parser_errposition_callback(&pcbstate,
pstate, aconst->location);
(gdb) n
334             return (Datum) (uintptr_t) X;
(gdb) step
DirectFunctionCall3Coll (func=0x555555b4da00 <bit_in>,
collation=collation@entry=0, arg1=93825004730856, arg2=arg2@entry=0,
arg3=arg3@entry=18446744073709551615) at fmgr.c:836
836     {
(gdb) n
840             InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL,
NULL);
(gdb)
849             result = (*func) (fcinfo);
(gdb)
[Inferior 1 (process 210169) exited with code 01]

This is for the 3rd function argument with making Datum in bit_in (which i
don't understand why) matches the error " " is not a valid binary digit at
character 1670 from "RETURN lpad($1, $2, ' ');"

Also a week older master compilation doesn't have this issue, so this should
narrow down the hunt for someone if this isn't something only i am seeing,
i'll leave it to someone who knows more about this region.


Best regards,
Ayoub Kazar


pgsql-bugs by date:

Previous
From: shveta malik
Date:
Subject: Re: Unexpected Standby Shutdown on sync_replication_slots change
Next
From: KAZAR Ayoub
Date:
Subject: Re: BUG #19028: INITDB fails post-bootstrap initialization with FATAL " " is not a valid binary digit at character 1