Skip to content

fix: auto-recover replicas with diverged timelines by re-cloning - #9637

Draft
armru wants to merge 3 commits into
mainfrom
dev/bug-history
Draft

armru wants to merge 3 commits into
mainfrom
dev/bug-history

Conversation

@armru

@armru armru commented Jan 7, 2026 •

Copy link
Copy Markdown
Member

fix: auto-recover replicas with diverged timelines by re-cloning

When a replica's timeline diverges from the primary after a failover
(e.g., due to network issues or WAL archiving lag), PostgreSQL fails
to start with "requested timeline X is not a child of this server's
history". This left replicas in a crash-loop requiring manual PVC
deletion to recover.

This fix adds automatic recovery by:

  • Detecting timeline mismatch between replica and primary during
    instance startup by checking cluster status
  • Exiting with a specific exit code (6) when divergence is detected
  • Operator detects this exit code and marks the instance as
    unrecoverable, triggering automatic PVC deletion and re-cloning
    via pg_basebackup

Closes #4990

@cnpg-bot cnpg-bot added backport-requested ◀️ This pull request should be backported to all supported releases release-1.25 release-1.28 labels Jan 7, 2026
@github-actions

github-actions Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

❗ By default, the pull request is configured to backport to all release branches.

  • To stop backporting this pr, remove the label: backport-requested ◀️ or add the label 'do not backport'
  • To stop backporting this pr to a certain release branch, remove the specific branch label: release-x.y

@armru

armru commented Jan 7, 2026

Copy link
Copy Markdown
Member Author

/test

@github-actions

github-actions Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

@armru armru changed the title fix: auto-recover replicas with diverged timelines using pg_rewind fix: auto-recover replicas with diverged timelines Jan 7, 2026
@armru
armru force-pushed the dev/bug-history branch 2 times, most recently from 56c6d16 to c60e639 Compare January 7, 2026 13:28
@armru armru changed the title fix: auto-recover replicas with diverged timelines fix: auto-recover replicas with diverged timelines by re-cloning Jan 7, 2026
@armru

armru commented Jan 7, 2026

Copy link
Copy Markdown
Member Author

/test

@github-actions

github-actions Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

armru added 2 commits January 12, 2026 15:38
When a replica's timeline diverges from the primary after a failover
(e.g., due to network issues or WAL archiving lag), PostgreSQL fails
to start with "requested timeline X is not a child of this server's
history". This left replicas in a crash-loop requiring manual PVC
deletion to recover.

This fix adds automatic recovery by:
- Detecting timeline mismatch between replica and primary during
  instance startup by checking cluster status
- Exiting with a specific exit code (6) when divergence is detected
- Operator detects this exit code and marks the instance as
  unrecoverable, triggering automatic PVC deletion and re-cloning
  via pg_basebackup

Closes #4990

Signed-off-by: Armando Ruocco <[email protected]>
Signed-off-by: Armando Ruocco <[email protected]>
@armru

armru commented Jan 12, 2026

Copy link
Copy Markdown
Member Author

/test

@github-actions

Copy link
Copy Markdown
Contributor

Signed-off-by: Armando Ruocco <[email protected]>
gbartolini pushed a commit that referenced this pull request Jan 14, 2026
…story files

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637 (auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
@dosubot dosubot Bot mentioned this pull request Jan 17, 2026
4 tasks done
mnencia added a commit that referenced this pull request Jan 20, 2026
…story files

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637 (auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
mnencia added a commit that referenced this pull request Jan 20, 2026
…story files (#9650)

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for
timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637
(auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
Signed-off-by: Armando Ruocco <[email protected]>
Co-authored-by: Armando Ruocco <[email protected]>
cnpg-bot pushed a commit that referenced this pull request Jan 20, 2026
…story files (#9650)

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for
timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637
(auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
Signed-off-by: Armando Ruocco <[email protected]>
Co-authored-by: Armando Ruocco <[email protected]>
(cherry picked from commit ef73994)
cnpg-bot pushed a commit that referenced this pull request Jan 20, 2026
…story files (#9650)

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for
timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637
(auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
Signed-off-by: Armando Ruocco <[email protected]>
Co-authored-by: Armando Ruocco <[email protected]>
(cherry picked from commit ef73994)
cnpg-bot pushed a commit that referenced this pull request Jan 20, 2026
…story files (#9650)

Replicas can crash-loop when orphaned "future timeline" .history files
exist in the WAL archive. This can occur during split-brain scenarios
or other conditions where timeline history files are created for
timelines
that the cluster never officially adopts.

This fix adds validation during WAL restore to prevent replicas from
downloading timeline history files with timeline IDs greater than the
cluster's current timeline. Primary instances retain full access.

The validation works by:
- Parsing timeline ID from .history filenames (e.g., 00000022.history)
- Checking if the instance is a primary or replica
- For replicas, rejecting files where fileTimeline > clusterTimeline
- Returning "file not found" to PostgreSQL for rejected files

This prevents PostgreSQL from ever seeing the problematic history file,
allowing normal recovery to proceed. Combined with PR #9637
(auto-recovery
via re-cloning), this provides complete coverage of timeline divergence
scenarios.

Closes #4188

Signed-off-by: Marco Nenciarini <[email protected]>
Signed-off-by: Armando Ruocco <[email protected]>
Co-authored-by: Armando Ruocco <[email protected]>
(cherry picked from commit ef73994)
@jmealo

jmealo commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

@armru I think the fix for #10419 overlaps with this a bit. Will follow-up on Slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-requested ◀️ This pull request should be backported to all supported releases release-1.28 release-1.30

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Replica does not come up: checkpoint not found in timeline

4 participants