sipeed/picoclaw · critical

line channel_secret and channel_access_token are required

Error message

line channel_secret and channel_access_token are required

What it means

Constructor validation error from NewLINEChannel: either ChannelSecret or ChannelAccessToken is empty, so the channel cannot be built. Both are required — the secret validates webhook signatures, the token authorizes Messaging API pushes. Fail-fast at construction.

Source

Thrown at pkg/channels/line/line.go:61

	config         *config.LINESettings
	client         *messaging_api.MessagingApiAPI
	botUserID      string   // Bot's user ID
	botBasicID     string   // Bot's basic ID (e.g. @216ru...)
	botDisplayName string   // Bot's display name for text-based mention detection
	replyTokens    sync.Map // chatID -> replyTokenEntry
	quoteTokens    sync.Map // chatID -> quoteToken (string)
	ctx            context.Context
	cancel         context.CancelFunc
}

// NewLINEChannel creates a new LINE channel instance.
func NewLINEChannel(
	bc *config.Channel,
	cfg *config.LINESettings,
	messageBus *bus.MessageBus,
) (*LINEChannel, error) {
	if cfg.ChannelSecret.String() == "" || cfg.ChannelAccessToken.String() == "" {
		return nil, fmt.Errorf("line channel_secret and channel_access_token are required")
	}

	client, err := messaging_api.NewMessagingApiAPI(
		cfg.ChannelAccessToken.String(),
		messaging_api.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
	)
	if err != nil {
		return nil, fmt.Errorf("failed to create LINE messaging client: %w", err)
	}

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

	return &LINEChannel{

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Set both channel_secret and channel_access_token (json keys) or the two env vars, from the LINE Developers Console > Messaging API credentials.
  2. After regenerating a token in the console, update config immediately — old tokens stop working.
  3. Ensure secret-manager injection actually populates both values (verify non-empty at startup).
  4. Prefer a channel access token (long-lived) over short-lived tokens to avoid frequent rotation failures.

Example fix

# before
{ "type": "line", "settings": { "channel_secret": "***" } }

# after
{ "type": "line", "settings": { "channel_secret": "***", "channel_access_token": "***" } }
Defensive patterns

Strategy: validation

Validate before calling

if cfg.ChannelSecret.String() == "" || cfg.ChannelAccessToken.String() == "" {
    return fmt.Errorf("line settings incomplete: channel_secret and channel_access_token are required")
}

Try / catch

if _, err := line.NewLINEChannel(bc, cfg, messageBus); err != nil {
    log.Fatalf("channel config invalid: %v", err) // credentials missing: fix config before deploy
}

Prevention

When it happens

Trigger: A channel entry of type 'line' is configured with a missing/empty channel_secret or channel_access_token — absent JSON keys, or PICOCLAW_CHANNELS_LINE_CHANNEL_SECRET / PICOCLAW_CHANNELS_LINE_CHANNEL_ACCESS_TOKEN env vars unset.

Common situations: Token regenerated in the LINE Developers Console but only one of the two updated in config; secrets loaded from a vault that failed silently leaving empty strings; whitespace-only token after copy-paste (note: .String() is checked for empty only).

Related errors


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