sipeed/picoclaw · warning

failed to close discord session: %w

Error message

failed to close discord session: %w

What it means

Stop() reports this when session.Close() errors while tearing down the Discord websocket. By this point the channel is already non-running (SetRunning(false)), typing goroutines and contexts are canceled, so this is best-effort cleanup noise — typically 'use of closed connection' or a failed websocket close handshake.

Source

Thrown at pkg/channels/discord/discord.go:158

	// Stop all typing goroutines before closing session
	c.typingMu.Lock()
	for chatID, stop := range c.typingStop {
		close(stop)
		delete(c.typingStop, chatID)
	}
	c.typingMu.Unlock()

	// Cancel our context so typing goroutines using c.ctx.Done() exit
	if c.cancel != nil {
		c.cancel()
	}
	if c.progress != nil {
		c.progress.StopAll()
	}

	if err := c.session.Close(); err != nil {
		return fmt.Errorf("failed to close discord session: %w", err)
	}

	return nil
}

func (c *DiscordChannel) Send(ctx context.Context, msg bus.OutboundMessage) ([]string, error) {
	if !c.IsRunning() {
		return nil, channels.ErrNotRunning
	}

	channelID := msg.ChatID
	if channelID == "" {
		return nil, fmt.Errorf("channel ID is empty")
	}

	if len([]rune(msg.Content)) == 0 {
		return nil, nil
	}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Treat Stop errors as non-fatal: log a warning and continue shutdown
  2. Guard against double Stop with an IsRunning/once check before closing the session
  3. If the process is exiting anyway, a failed Close is harmless — the OS reclaims the socket

Example fix

// before
if err := c.session.Close(); err != nil {
    return fmt.Errorf("failed to close discord session: %w", err)
}

// after
if err := c.session.Close(); err != nil {
    logger.WarnCF("discord", "session close error (ignored)", map[string]any{"error": err.Error()})
}
return nil
Defensive patterns

Strategy: fallback

Try / catch

if err := ch.Stop(ctx); err != nil {
    // shutdown is best-effort: log and continue teardown
    log.Printf("warn: discord stop: %v", err)
}

Prevention

When it happens

Trigger: Stop called twice (second Close errors), stopping after the network/voice connection already dropped, or the websocket close handshake failing during shutdown.

Common situations: Double-stop from manager plus signal handler, shutdown after network loss, orchestrators that call Stop on both SIGTERM and cleanup.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/919a4e1dfcbe4faf. Report an issue: GitHub.