sipeed/picoclaw · error

slack auth test failed: %w

Error message

slack auth test failed: %w

What it means

SlackChannel.Start calls api.AuthTest() to validate the bot token and capture the bot's user/team IDs before opening the Socket Mode event loop. Any failure — invalid/revoked token, missing scope, network error, Slack outage — is wrapped as "slack auth test failed" with the original error intact. This is the first real network call the channel makes, so it is where bad credentials surface.

Source

Thrown at pkg/channels/slack/slack.go:90

		postTextFn: func(ctx context.Context, channelID, threadTS, text string) error {
			opts := []slack.MsgOption{slack.MsgOptionText(text, false)}
			if threadTS != "" {
				opts = append(opts, slack.MsgOptionTS(threadTS))
			}
			_, _, err := api.PostMessageContext(ctx, channelID, opts...)
			return err
		},
	}, nil
}

func (c *SlackChannel) Start(ctx context.Context) error {
	logger.InfoC("slack", "Starting Slack channel (Socket Mode)")

	c.ctx, c.cancel = context.WithCancel(ctx)

	authResp, err := c.api.AuthTest()
	if err != nil {
		return fmt.Errorf("slack auth test failed: %w", err)
	}
	c.botUserID = authResp.UserID
	c.teamID = authResp.TeamID

	logger.InfoCF("slack", "Slack bot connected", map[string]any{
		"bot_user_id": c.botUserID,
		"team":        authResp.Team,
	})

	go c.eventLoop()

	go func() {
		if err := c.socketClient.RunContext(c.ctx); err != nil {
			if c.ctx.Err() == nil {
				logger.ErrorCF("slack", "Socket Mode connection error", map[string]any{
					"error": err.Error(),
				})
			}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Unwrap the error: slack's client returns invalid_auth / token_expired reasons that name the exact problem; re-issue the affected token and update config.
  2. Verify the pairing: bot_token is xoxb- from the same Slack app as the xapp- app token.
  3. Test connectivity to slack.com (curl https://slack.com/api/auth.test) from the same host/container.
  4. If Slack reports a transient 5xx or network timeout, retry Start with backoff.

Example fix

// before
if err := slk.Start(ctx); err != nil { log.Fatal(err) }

// after: distinguish auth failure from transient error
if err := slk.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "invalid_auth") ||
       strings.Contains(err.Error(), "token_expired") {
        log.Fatal("slack: rotate the bot token in config") // permanent
    }
    log.Printf("slack: transient start failure, retrying: %v", err)
    time.Sleep(5 * time.Second)
    return slk.Start(ctx)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight the same call Start uses
resp, err := slackClient.AuthTest()
if err != nil { return fmt.Errorf("slack token invalid before start: %w", err) }
_ = resp

Try / catch

if err := ch.Start(ctx); err != nil {
    msg := err.Error()
    switch {
    case strings.Contains(msg, "invalid_auth"), strings.Contains(msg, "token_expired"):
        rotateTokenAndRestart() // permanent
    case strings.Contains(msg, "slack auth test failed"): // wrapped network/5xx
        retryWithBackoff(func() error { return ch.Start(ctx) })
    }
}

Prevention

When it happens

Trigger: Start() with an expired/revoked bot token (token_rotation/deactivated app); bot token lacking the auth.test permission; no egress to slack.com; Slack 5xx incident; tokens swapped between apps (xoxb of app A with xapp of app B).

Common situations: Reinstalling the Slack app which rotates the bot token while config keeps the old one; workspace admins revoking the app; corporate proxies blocking slack.com; using an app-level token in the bot_token field by mistake.

Related errors


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