Overview
I encountered an issue where the Omeka S OAI-PMH repository’s resumptionToken was outputting a [badResumptionToken] error even though the token was still within its expiration period.

Here are my notes on how to address this bug.
Solution
By adding a comparison between $currentTime and $expirationTime to the following file, tokens within their expiration period are now properly retained.
...
private function resumeListResponse($token): void
{
$api = $this->serviceLocator->get('ControllerPluginManager')->get('api');
$expiredTokens = $api->search('oaipmh_repository_tokens', [
'expired' => true,
])->getContent();
foreach ($expiredTokens as $expiredToken) {
$currentTime = new \DateTime(); // Added
$expirationTime = $expiredToken->expiration(); // Added
if (!$expiredToken || $currentTime > $expirationTime) { // Added
$api->delete('oaipmh_repository_tokens', $expiredToken->id());
} // Added
}
There were cases where things worked without this fix, so there may be differences depending on the PHP version, etc.
References
For reference, I checked the contents of the table created by the OAI-PMH repository module.
mysql> DESCRIBE oaipmhrepository_token;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| verb | varchar(15) | NO | | NULL | |
| metadata_prefix | varchar(190) | NO | | NULL | |
| cursor | int | NO | | NULL | |
| from | datetime | YES | | NULL | |
| until | datetime | YES | | NULL | |
| set | varchar(190) | YES | | NULL | |
| expiration | datetime | NO | MUL | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
8 rows in set (0.01 sec)
mysql> SELECT * FROM oaipmhrepository_token LIMIT 10;
+----+-------------+-----------------+--------+------+-------+------+---------------------+
| id | verb | metadata_prefix | cursor | from | until | set | expiration |
+----+-------------+-----------------+--------+------+-------+------+---------------------+
| 8 | ListRecords | oai_dc | 50 | NULL | NULL | NULL | 2024-10-10 07:07:40 |
| 9 | ListRecords | oai_dc | 50 | NULL | NULL | NULL | 2024-10-10 07:07:44 |
| 10 | ListRecords | oai_dc | 100 | NULL | NULL | NULL | 2024-10-10 07:07:49 |
| 11 | ListRecords | oai_dc | 150 | NULL | NULL | NULL | 2024-10-10 07:07:54 |
| 12 | ListRecords | oai_dc | 50 | NULL | NULL | NULL | 2024-10-10 08:16:31 |
| 13 | ListRecords | oai_dc | 100 | NULL | NULL | NULL | 2024-10-10 08:16:36 |
| 14 | ListRecords | oai_dc | 150 | NULL | NULL | NULL | 2024-10-10 08:16:41 |
| 15 | ListRecords | oai_dc | 200 | NULL | NULL | NULL | 2024-10-10 08:16:44 |
+----+-------------+-----------------+--------+------+-------+------+---------------------+
Summary
There may be some incomplete aspects, but I hope this serves as a useful reference.