chenhg5/cc-connect · error

start thread in channel %s: %w

Error message

start thread in channel %s: %w

What it means

resolveCronReplyTarget creates a fresh standalone thread in the resolved parent channel via ops.StartStandaloneThread. Failure is wrapped as "start thread in channel <id>: <cause>". This is the cron equivalent of error 1124 and inherits all the nil-session, permission, and channel-type constraints of ThreadStart.

Source

Thrown at platform/discord/discord.go:455

		if ch.ParentID == "" {
			return "", replyContext{}, core.ErrNotSupported
		}
		parent, err := ops.ResolveChannel(ch.ParentID)
		if err != nil {
			return "", replyContext{}, fmt.Errorf("resolve parent channel %s: %w", ch.ParentID, err)
		}
		parentChannelID = ch.ParentID
		parentType = parent.Type
	}

	threadType, ok := standaloneThreadType(parentType)
	if !ok {
		return "", replyContext{}, core.ErrNotSupported
	}

	thread, err := ops.StartStandaloneThread(parentChannelID, freshThreadName(title), threadType, 1440)
	if err != nil {
		return "", replyContext{}, fmt.Errorf("start thread in channel %s: %w", parentChannelID, err)
	}
	if err := ops.JoinThread(thread.ID); err != nil {
		slog.Debug("discord: join fresh thread failed", "thread", thread.ID, "error", err)
	}

	rc := replyContext{channelID: thread.ID, threadID: thread.ID}
	return buildThreadSessionKey(thread.ID), rc, nil
}

// RegisterCommands registers bot commands with Discord for the slash command menu.
func (p *Platform) RegisterCommands(commands []core.BotCommandInfo) error {
	// Wait for Ready event to ensure appID is populated
	select {
	case <-p.readyCh:
	case <-time.After(15 * time.Second):
		return fmt.Errorf("discord: timed out waiting for Ready event")
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the wrapped cause; if it is "session not initialized", ensure Start() runs before the scheduler.
  2. Grant the bot thread-creation permissions in the parent channel.
  3. Move the cron target to an active, non-archived guild text channel.
  4. Add a fallback that posts the cron output to the parent channel (no thread) when thread creation fails.

Example fix

// before
thread, err := ops.StartStandaloneThread(parentChannelID, freshThreadName(title), threadType, 1440)
if err != nil {
    return "", replyContext{}, fmt.Errorf("start thread in channel %s: %w", parentChannelID, err)
}
// after
thread, err := ops.StartStandaloneThread(parentChannelID, freshThreadName(title), threadType, 1440)
if err != nil {
    slog.Warn("discord: standalone thread creation failed for cron", "channel", parentChannelID, "error", err)
    rc := replyContext{channelID: parentChannelID}
    return buildThreadSessionKey(parentChannelID), rc, nil
}
Defensive patterns

Strategy: fallback

Validate before calling

perm, err := session.State.UserChannelPermissions(botID, parentChannelID)
canThread := err == nil && perm&discordgo.PermissionCreatePublicThreads != 0

Try / catch

thread, err := ops.StartStandaloneThread(parentChannelID, name, threadType, 1440)
if err != nil {
    slog.Warn("discord: cron thread creation failed; posting to channel", "channel", parentChannelID, "error", err)
    return buildThreadSessionKey(parentChannelID), replyContext{channelID: parentChannelID}, nil
}

Prevention

When it happens

Trigger: ops.StartStandaloneThread(parentChannelID, name, threadType, 1440) fails: bot lacks thread-creation permission in the parent channel, the parent is archived/locked or not a guild text/announcement/forum channel, or the sessionThreadOps guard rejects a nil session.

Common situations: Cron jobs targeting channels where the bot's role lacks "Create Public Threads", forum channels with restricted post creation, archived channels, or the platform being shut down when the cron fires.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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