sipeed/picoclaw · warning · channels.ErrTemporary
whatsapp connection not established: %w
Error message
whatsapp connection not established: %w
What it means
Returned by WhatsAppNativeChannel.Send when the whatsmeow client is nil (channel not started) or client.IsConnected() is false (socket dropped). It wraps channels.ErrTemporary, so the channel manager schedules an exponential-backoff retry instead of dead-lettering the message.
Source
Thrown at pkg/channels/whatsapp_native/whatsapp_native.go:425
c.HandleInboundContext(c.runCtx, chatID, content, mediaPaths, inboundCtx, sender)
}
func (c *WhatsAppNativeChannel) Send(ctx context.Context, msg bus.OutboundMessage) ([]string, error) {
if !c.IsRunning() {
return nil, channels.ErrNotRunning
}
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
c.mu.Lock()
client := c.client
c.mu.Unlock()
if client == nil || !client.IsConnected() {
return nil, fmt.Errorf("whatsapp connection not established: %w", channels.ErrTemporary)
}
// Detect unpaired state: the client is connected (to WhatsApp servers)
// but has not completed QR-login yet, so sending would fail.
if client.Store.ID == nil {
return nil, fmt.Errorf("whatsapp not yet paired (QR login pending): %w", channels.ErrTemporary)
}
to, err := parseJID(msg.ChatID)
if err != nil {
return nil, fmt.Errorf("invalid chat id %q: %w", msg.ChatID, err)
}
waMsg := &waE2E.Message{
Conversation: proto.String(msg.Content),
}
if _, err = client.SendMessage(ctx, to, waMsg); err != nil {View on GitHub (pinned to 49183d7e8d)
Solutions
- Check the channel's running/connected state before sending, or rely on the manager's retry.
- Restore network connectivity; whatsmeow reconnect paths will flip IsConnected() true again.
- Inspect logs for preceding disconnect events to learn why the socket dropped.
- If permanent (channel intentionally stopped), pause the channel config so queued sends stop.
Defensive patterns
Strategy: retry
Validate before calling
if !ch.IsRunning() {
return errors.New("whatsapp native channel not running")
} Type guard
func isTemporary(err error) bool { return errors.Is(err, channels.ErrTemporary) } Try / catch
if _, err := ch.Send(ctx, msg); err != nil {
if errors.Is(err, channels.ErrTemporary) {
// not connected yet: backoff; whatsmeow reconnect or Start will restore
}
} Prevention
- Check IsRunning() before enqueueing sends.
- Monitor disconnect/reconnect events to anticipate send failures.
- Let manager backoff handle transient disconnect windows rather than failing fast.
When it happens
Trigger: Send() invoked before Start completes, after Stop, or while whatsmeow is disconnected - e.g. the websocket dropped due to network loss and the event handler's reconnect logic has not yet re-established IsConnected().
Common situations: Outbound message queued while the WhatsApp session is down; transient internet outage on the host; the device re-connecting after sleep; sends racing a restart.
Related errors
- whatsapp send: %w
- whatsapp connection not established: %w
- whatsapp send: %w
- create session store dir: %w
- get device store: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/1be9d23eda546e4d.
Report an issue: GitHub.