Summary
#557 lengthened migrate_adapter's MIN_LEDGER_GAP cooldown from ~1 minute to ~1 day. The migration keeper (packages/stellar-sdk-helpers/src/migration-keeper.ts) does not special-case the resulting MigrationCooldownNotMet rejection: it falls into the generic failure path, gets pushed to failures[], and api/v1/keepers/rebalance.ts returns HTTP 500 whenever failures.length > 0.
Motivation
While the cooldown was ~1 minute, a single MigrationCooldownNotMet failure on the run immediately after begin_migration was harmless noise, gone by the next hourly run. With the cooldown now ~1 day, every hourly run during that window hits the same rejection, producing roughly 24 consecutive HTTP 500s and failure log entries per migration. This creates sustained false-positive paging/monitoring noise during exactly the window #557 intends observers to calmly watch for a genuinely malicious begin_migration call, undermining that goal.
Proposed Solution
Special-case MigrationCooldownNotMet the same way isStaleAdapterError already is: detect it (the raw simulation error surfaces as Error(Contract, #20), matching MigrationCooldownNotMet = 20 in packages/contracts/vault/src/errors.rs) and report it as a skipped outcome with an informative reason, not a failures entry, so the keeper's HTTP status and logs correctly reflect "cooldown in progress, working as intended" rather than "something is wrong."
Scope
| Field |
Value |
| Area |
SDK / API |
| Protocol affected |
None |
| Network |
Both |
| Breaking change? |
No |
Acceptance Criteria
Additional Context
Identified during review of #710. Not fixed there since it is a keeper/monitoring-quality issue, not a fund-safety one, and deserves its own dedicated fix and tests rather than being folded into a contract-focused PR.
Summary
#557lengthenedmigrate_adapter'sMIN_LEDGER_GAPcooldown from ~1 minute to ~1 day. The migration keeper (packages/stellar-sdk-helpers/src/migration-keeper.ts) does not special-case the resultingMigrationCooldownNotMetrejection: it falls into the generic failure path, gets pushed tofailures[], andapi/v1/keepers/rebalance.tsreturns HTTP 500 wheneverfailures.length > 0.Motivation
While the cooldown was ~1 minute, a single
MigrationCooldownNotMetfailure on the run immediately afterbegin_migrationwas harmless noise, gone by the next hourly run. With the cooldown now ~1 day, every hourly run during that window hits the same rejection, producing roughly 24 consecutive HTTP 500s and failure log entries per migration. This creates sustained false-positive paging/monitoring noise during exactly the window #557 intends observers to calmly watch for a genuinely maliciousbegin_migrationcall, undermining that goal.Proposed Solution
Special-case
MigrationCooldownNotMetthe same wayisStaleAdapterErroralready is: detect it (the raw simulation error surfaces asError(Contract, #20), matchingMigrationCooldownNotMet = 20inpackages/contracts/vault/src/errors.rs) and report it as askippedoutcome with an informative reason, not afailuresentry, so the keeper's HTTP status and logs correctly reflect "cooldown in progress, working as intended" rather than "something is wrong."Scope
Acceptance Criteria
MigrationCooldownNotMetis detected and reported asskipped, notfailuresapps/docs/operations/migration-keeper.mdupdated to reflect the fixed behaviorAdditional Context
Identified during review of #710. Not fixed there since it is a keeper/monitoring-quality issue, not a fund-safety one, and deserves its own dedicated fix and tests rather than being folded into a contract-focused PR.