From c6007d8909f2dee64a8fbd664aa97dd89f944884 Mon Sep 17 00:00:00 2001 From: Nitin Jadhav Date: Thu, 19 Feb 2026 08:28:34 +0000 Subject: [PATCH 1/2] Lower PANIC to FATAL for missing checkpoint error in no-backup_label path Crash recovery without a backup_label currently PANICs if the checkpoint record cannot be found. Report this as FATAL instead, as missing WAL is a plausible operational failure and the backup_label recovery path already treats it as a FATAL error. --- src/backend/access/transam/xlogrecovery.c | 2 +- ...pl => 050_missing_redo_no_backup_label.pl} | 0 .../052_missing_checkpoint_no_backup_label.pl | 60 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) rename src/test/recovery/t/{050_redo_segment_missing.pl => 050_missing_redo_no_backup_label.pl} (100%) create mode 100644 src/test/recovery/t/052_missing_checkpoint_no_backup_label.pl diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index c0c2744d45b..857dbb33f19 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -798,7 +798,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, * can't read the last checkpoint because this allows us to * simplify processing around checkpoints. */ - ereport(PANIC, + ereport(FATAL, errmsg("could not locate a valid checkpoint record at %X/%08X", LSN_FORMAT_ARGS(CheckPointLoc))); } diff --git a/src/test/recovery/t/050_redo_segment_missing.pl b/src/test/recovery/t/050_missing_redo_no_backup_label.pl similarity index 100% rename from src/test/recovery/t/050_redo_segment_missing.pl rename to src/test/recovery/t/050_missing_redo_no_backup_label.pl diff --git a/src/test/recovery/t/052_missing_checkpoint_no_backup_label.pl b/src/test/recovery/t/052_missing_checkpoint_no_backup_label.pl new file mode 100644 index 00000000000..1f2182f9f31 --- /dev/null +++ b/src/test/recovery/t/052_missing_checkpoint_no_backup_label.pl @@ -0,0 +1,60 @@ +# Copyright (c) 2025-2026, PostgreSQL Global Development Group +# +# Verify crash recovery behavior when the WAL segment containing the +# checkpoint record referenced by pg_controldata is missing, in the code path +# where there is no backup_label file. +# +# Expected behavior: startup fails with FATAL and logs a message about +# not being able to locate a checkpoint record. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('testnode'); +$node->init; +$node->append_conf('postgresql.conf', 'log_checkpoints = on'); +$node->start; + +# Force a checkpoint so pg_controldata points to a checkpoint record we can target. +$node->safe_psql('postgres', 'CHECKPOINT;'); + +# Retrieve the checkpoint LSN and derive the WAL segment name. +my $checkpoint_lsn = $node->safe_psql('postgres', + "SELECT checkpoint_lsn FROM pg_control_checkpoint()"); +my $checkpoint_walfile = + $node->safe_psql('postgres', "SELECT pg_walfile_name('$checkpoint_lsn')"); + +ok($checkpoint_walfile ne '', "derived checkpoint WAL file name: $checkpoint_walfile"); + +# Stop the node. +$node->stop('immediate'); + +# Remove the WAL segment containing the checkpoint record. +my $walpath = $node->data_dir . "/pg_wal/$checkpoint_walfile"; +ok(-f $walpath, "checkpoint WAL file exists before deletion: $walpath"); + +unlink $walpath + or die "could not remove WAL file $walpath: $!"; + +ok(!-e $walpath, "checkpoint WAL file removed: $walpath"); + +# Use run_log instead of node->start because this test expects that +# the server ends with an error during recovery. +run_log( + [ + 'pg_ctl', + '--pgdata' => $node->data_dir, + '--log' => $node->logfile, + 'start', + ]); + +# Confirm that recovery has failed, as expected. +my $logfile = slurp_file($node->logfile()); +ok( $logfile =~ + qr/FATAL: .* could not locate a valid checkpoint record at .*/, + "FATAL logged for missing checkpoint record (no backup_label path)"); + +done_testing(); \ No newline at end of file -- 2.43.0