The problem was originally reported in https://github.com/bitcoin/bitcoin/issues/22450#issuecomment-880602891. This is a dedicated issue to track it independently because it is a different problem than the one reported in #22450 OP/description.

> If the same I2P address appears in multiple new buckets, then the first time this loop finds that address, it'll update the port and reposition it in that bucket. Any subsequent times that the address is encountered, it will already have had its port updated so the inner loop will `continue` ...

Thanks, @jnewbery!
{
        return GetNewBucket(nKey, source, asmap);
    }
    
    int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
    
    bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
    
    double GetChance(int64_t nNow = GetAdjustedTime()) const;
};
/** Stochastic address manager
 *
 * Design goals:
 *  * Keep the address tables in-memory, and asynchronously dump the entire table to peers.dat.
 *  * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
 *
 * To that end:
 *  * Addresses are organized into buckets.
 *    * Addresses that have not yet been tried go into 1024 "new" buckets.
 *      * Based on the address range (/16 for IPv4) of the source of information, 64 buckets are selected at random.
 *      * The actual bucket is chosen from one of these, based on the range in which the address itself is located.
 *      * One single address can occur in up to 8 different buckets to increase selection chances for addresses that
 *        are seen frequently. The chance for increasing this multiplicity decreases exponentially.
 *      * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
 *        ones) is removed from it first.