diff --git a/pkg/channels/buzz/buzz.go b/pkg/channels/buzz/buzz.go index 4bc4386e..643d70fc 100644 --- a/pkg/channels/buzz/buzz.go +++ b/pkg/channels/buzz/buzz.go @@ -195,6 +195,12 @@ func (c *BuzzChannel) subscribeAuthed( "pubkey": c.publicKey, }) + // postAuthGrace is how long we wait after re-subscribing for either + // EOSE (relay sends end-of-stored-events) or a rejection. If neither + // arrives, the relay accepted the subscription but doesn't send EOSE — + // which is fine, we just start consuming events. + const postAuthGrace = 3 * time.Second + authed, err := c.relay.Subscribe(ctx, filters) if err != nil { return nil, fmt.Errorf("buzz subscribe after auth failed: %w", err) @@ -208,8 +214,14 @@ func (c *BuzzChannel) subscribeAuthed( // A second rejection means the identity is not permitted, not that // the handshake was mistimed — retrying would loop forever. return nil, fmt.Errorf("buzz relay rejected subscription after auth: %s", reason) - case <-time.After(subscribeTimeout): - return nil, fmt.Errorf("buzz timed out waiting for subscription after auth") + case <-time.After(postAuthGrace): + // No EOSE and no rejection within the grace period — the relay + // accepted the subscription. Some relays (including Buzz) don't + // send EOSE after auth, so this is the expected success path. + logger.InfoCF("buzz", "Subscription accepted after auth (no EOSE)", map[string]any{ + "relay": c.config.RelayURL, + }) + return authed, nil } case <-time.After(subscribeTimeout):