chenhg5/cc-connect · error

create device: %w

Error message

create device: %w

What it means

runConnection registers a Mercury device via the Webex device registration API before opening the WebSocket. If CreateDevice fails (non-2xx or transport error) the error is wrapped as 'create device: %w' and the reconnect loop surfaces it.

Source

Thrown at platform/webex/webex.go:306

		case <-ctx.Done():
			return
		case <-time.After(backoff):
		}
	}
}

func (p *Platform) lifecycle() core.PlatformLifecycleHandler {
	p.mu.RLock()
	defer p.mu.RUnlock()
	return p.lifecycleHandler
}

// runConnection registers a device, dials the WebSocket, and reads until the
// connection drops or the context is cancelled.
func (p *Platform) runConnection(ctx context.Context) error {
	dev, err := p.client.CreateDevice(ctx)
	if err != nil {
		return fmt.Errorf("create device: %w", err)
	}
	p.mu.Lock()
	prevDevice := p.deviceURL
	p.deviceURL = dev.URL
	p.mu.Unlock()
	if prevDevice != "" && prevDevice != dev.URL {
		if err := p.client.DeleteDevice(ctx, prevDevice); err != nil {
			slog.Debug("webex: delete stale device failed", "error", err)
		}
	}

	header := map[string][]string{"Authorization": {"Bearer " + p.token}}
	conn, _, err := websocket.DefaultDialer.DialContext(ctx, dev.WebSocketURL, header)
	if err != nil {
		return fmt.Errorf("dial websocket: %s", core.RedactToken(err.Error(), p.token))
	}
	defer func() { _ = conn.Close() }()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Refresh the bot token — 401 here means credentials went stale after startup
  2. Check connectivity to webexapis.com (proxy, firewall, DNS)
  3. If this fires repeatedly, add exponential backoff to reconnect attempts to avoid rate limiting
  4. Inspect the wrapped cause for the precise status code and act on it (429 → back off, 403 → scopes)

Example fix

// before
// reconnect loop: immediate retry
for { runConnection(ctx) }
// after
for {
    if err := runConnection(ctx); err != nil {
        backoff = min(backoff*2, 5*time.Minute)
    }
    select { case <-ctx.Done(): return; case <-time.After(backoff): }
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure token valid and network reachable before the run loop:
// curl -f -H "Authorization: Bearer $TOKEN" https://webexapis.com/v1/people/me

Try / catch

for {
    err := runConnection(ctx)
    if ctx.Err() != nil { return }
    slog.Warn("reconnecting", "err", err)
    select { case <-ctx.Done(): return; case <-time.After(backoff): }
    backoff = min(backoff*2, maxBackoff)
}

Prevention

When it happens

Trigger: POST to the Webex devices endpoint returns 401/403/5xx or the HTTP transport fails (DNS, TLS, timeout) each time the connection is (re)established.

Common situations: Token expired mid-run so re-registration fails on reconnect; Webex outage blocking device registration; network restrictions/proxy blocking webexapis.com; rate limiting from aggressive reconnect loops.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a24eb3bf48fbf3d5. Report an issue: GitHub.