sipeed/picoclaw · error

slack bot_token and app_token are required

Error message

slack bot_token and app_token are required

What it means

NewSlackChannel requires both a bot token (xoxb-..., used for Web API calls) and an app-level token (xapp-..., used for Socket Mode). Empty values are rejected before any Slack client is built. Socket Mode cannot work without the app token's connections:write scope, so this is a fail-fast guard rather than a recoverable runtime condition.

Source

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

	ctx          context.Context
	cancel       context.CancelFunc
	pendingAcks  sync.Map
	uploadFileFn func(context.Context, slack.UploadFileParameters) error
	postTextFn   func(context.Context, string, string, string) error
}

type slackMessageRef struct {
	ChannelID string
	Timestamp string
}

func NewSlackChannel(
	bc *config.Channel,
	cfg *config.SlackSettings,
	messageBus *bus.MessageBus,
) (*SlackChannel, error) {
	if cfg.BotToken.String() == "" || cfg.AppToken.String() == "" {
		return nil, fmt.Errorf("slack bot_token and app_token are required")
	}

	api := slack.New(
		cfg.BotToken.String(),
		slack.OptionAppLevelToken(cfg.AppToken.String()),
	)

	socketClient := socketmode.New(api)

	base := channels.NewBaseChannel("slack", cfg, messageBus, bc.AllowFrom,
		channels.WithMaxMessageLength(40000),
		channels.WithGroupTrigger(bc.GroupTrigger),
		channels.WithReasoningChannelID(bc.ReasoningChannelID),
	)

	return &SlackChannel{
		BaseChannel:  base,
		config:       cfg,

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Set both settings: bot_token (starts with xoxb-) and app_token (starts with xapp-) in channels.<name>.settings for the slack channel.
  2. Create the app-level token in the Slack app config (App-Level Tokens, scope connections:write) if you do not have one.
  3. Verify env vars if configuring via environment: exact PICOCLAW_CHANNELS_SLACK_* names, exported in the service unit/container.
  4. Install the app to the workspace so the bot token is valid.

Example fix

# before
channels:
  slack:
    type: slack
    settings:
      bot_token: "xoxb-123-..."
      # app_token missing

# after
channels:
  slack:
    type: slack
    settings:
      bot_token: "xoxb-123-..."
      app_token: "xapp-1-A012345-..."  # scope: connections:write
Defensive patterns

Strategy: validation

Validate before calling

func slackTokensPresent(cfg *config.SlackSettings) error {
    if cfg.BotToken.String() == "" || cfg.AppToken.String() == "" {
        return fmt.Errorf("slack needs bot_token (xoxb-) and app_token (xapp-)")
    }
    if !strings.HasPrefix(cfg.BotToken.String(), "xoxb-") || !strings.HasPrefix(cfg.AppToken.String(), "xapp-") {
        return fmt.Errorf("slack tokens look swapped: bot=xoxb-, app=xapp-")
    }
    return nil
}

Try / catch

// Go: constructor returns this error synchronously; check it at channel creation and fail deployment config validation, not at runtime

Prevention

When it happens

Trigger: Constructing a slack channel with slack settings where bot_token or app_token (json keys bot_token, app_token; env PICOCLAW_CHANNELS_SLACK_BOT_TOKEN per pkg/config/config.go:587) is empty or unset; providing only one of the two tokens; env var names misspelled so SecureString stays empty.

Common situations: Creating a Slack app and copying only the bot token; forgetting to generate an app-level token under Basic Information > App-Level Tokens with connections:write; deploying with only PICOCLAW_CHANNELS_SLACK_BOT_TOKEN set; tokens stored in a secret manager that returns empty on permission errors.

Related errors


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