chenhg5/cc-connect · error
tuitui: team_id not found for channel %q
Error message
tuitui: team_id not found for channel %q
What it means
For channel-type IDs, SendChannelPost must translate the channel into a teams chat ID, which requires the owning team's ID. It fetches channel info via getChannelInfo and, if the returned map has no non-empty "team_id", fails with this error naming the channel. The channel exists but is not associated with a team the bot can resolve.
Source
Thrown at platform/tuitui/tuitui.go:222
}
if strings.TrimSpace(markdown) == "" {
return fmt.Errorf("tuitui: markdown is required")
}
chatID := channelID
if guessChatType(channelID) == chatTypeChannel {
if parentID = strings.TrimSpace(parentID); parentID != "" {
target := teamsParseChatID(channelID)
chatID = teamsBuildChatID(target["team_id"], target["channel_id"], parentID)
}
} else {
info, err := p.getChannelInfo(ctx, channelID)
if err != nil {
return err
}
teamID := stringFromAny(info["team_id"])
if teamID == "" {
return fmt.Errorf("tuitui: team_id not found for channel %q", channelID)
}
chatID = teamsBuildChatID(teamID, channelID, strings.TrimSpace(parentID))
}
return p.sendText(ctx, replyContext{chatID: chatID, chatType: chatTypeChannel}, markdown)
}
func (p *Platform) SendImage(ctx context.Context, replyCtx any, img core.ImageAttachment) error {
name := img.FileName
if name == "" {
name = "image"
}
mediaID, _, err := p.uploadMedia(ctx, img.Data, img.MimeType, name, "image")
if err != nil {
return fmt.Errorf("tuitui: upload image: %w", err)
}
rctx, err := requireReplyContext(replyCtx)
if err != nil {
return errView on GitHub (pinned to 4000b2338a)
Solutions
- Add the bot to the team that owns the channel and grant scopes so channel info includes team_id.
- Verify the channel ID is correct and still active by calling getChannelInfo directly and inspecting the response.
- Configure an explicit team-to-channel mapping (or pass a fully-qualified teams chat ID) instead of relying on lookup.
Example fix
// before
info, _ := p.GetChannelInfo(ctx, chID) // returns no team_id
p.SendChannelPost(ctx, chID, md, "")
// after
info, err := p.GetChannelInfo(ctx, chID)
if err != nil || stringFromAny(info["team_id"]) == "" {
return fmt.Errorf("cannot resolve team for channel %s; check bot membership", chID)
}
p.SendChannelPost(ctx, chID, md, "") Defensive patterns
Strategy: try-catch
Validate before calling
info, err := p.GetChannelInfo(ctx, chID)
if err == nil && stringFromAny(info["team_id"]) == "" {
return fmt.Errorf("team not resolvable for %s", chID)
} Type guard
func teamResolvable(info map[string]any) bool {
tid, _ := info["team_id"].(string)
return tid != ""
} Try / catch
if err := p.SendChannelPost(ctx, chID, md, parent); err != nil && strings.Contains(err.Error(), "team_id not found") {
log.Error("bot may not be a member of the owning team", "channel", chID, "cause", err)
} Prevention
- Ensure the bot is added to every team whose channels you post to.
- Cache and periodically refresh channel→team mappings.
- Pre-resolve team IDs during setup and fail fast in config checks.
When it happens
Trigger: Calling SendChannelPost with a channel-type ID whose getChannelInfo response lacks "team_id" or returns an empty string for it.
Common situations: Posting to a channel whose team membership is not visible to the bot (missing scope or bot not added to the team); stale channel metadata after the channel was moved/archived; API returned partial channel info.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- no session found for project %q with key %q
- project %q has no feishu/lark platform
- session %q not found
- project %q not found
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/007ce5108b9d30d0.
Report an issue: GitHub.