I think I found what happened here. One WAL record can be split between WAL files.
In XLogReadRecord, if last WAL record is incomplete, it try to get next WAL: /* Copy the first fragment of the record from the first page. */ memcpy(state->readRecordBuf, state->readBuf + RecPtr % XLOG_BLCKSZ, len); buffer = state->readRecordBuf + len; gotlen = len; do { /* Calculate pointer to beginning of next page */ targetPagePtr += XLOG_BLCKSZ; /* Wait for the next page to become available */ readOff = ReadPageInternal(state, targetPagePtr, Min(total_len - gotlen + SizeOfXLogShortPHD, XLOG_BLCKSZ)); if (readOff < 0) goto err; but in my case next WAL not yet in archive (archive_timeout=0 in master) and it clean cache: err: /* * Invalidate the xlog page we've cached. We might read from a different * source after failure. */ state->readSegNo = 0; state->readOff = 0; state->readLen = 0; PG switch to streaming and last WAL (00000001000000000000002B for example) still not replayed completely. We do not use streaming and it switch back to archive: LOG: restored log file "00000001000000000000002B" from archive ... DEBUG: could not restore file "00000001000000000000002C" from archive: child process exited with exit code 1 DEBUG: switched WAL source from archive to stream after failure DEBUG: switched WAL source from stream to archive after failure Now it must reread first part of last WAL record from 00000001000000000000002B, but XLogFileReadAnyTLI is _always_ read from the archive first, even if this file is already in pg_xlog: if (source == XLOG_FROM_ANY || source == XLOG_FROM_ARCHIVE) { fd = XLogFileRead(segno, emode, tli, XLOG_FROM_ARCHIVE, true); if (fd != -1) { elog(DEBUG1, "got WAL segment from archive"); if (!expectedTLEs) expectedTLEs = tles; return fd; } } if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_XLOG) { fd = XLogFileRead(segno, emode, tli, XLOG_FROM_PG_XLOG, true); if (fd != -1) { if (!expectedTLEs) expectedTLEs = tles; return fd; } } Well, I think we'll be able to cache locally the last WAL file in restore_command if needed :-) -- Sergey Burladyan