chenhg5/cc-connect · error

tuitui: markdown is required

Error message

tuitui: markdown is required

What it means

SendChannelPost validates that the markdown body is non-empty after trimming. A post with no content cannot be rendered by TuiTui, so the call is rejected before building the payload. It runs right after the channel ID check.

Source

Thrown at platform/tuitui/tuitui.go:206

	}
	return nil
}

func (p *Platform) Reply(ctx context.Context, replyCtx any, content string) error {
	return p.sendText(ctx, replyCtx, content)
}

func (p *Platform) Send(ctx context.Context, replyCtx any, content string) error {
	return p.sendText(ctx, replyCtx, content)
}

func (p *Platform) SendChannelPost(ctx context.Context, channelID, markdown, parentID string) error {
	channelID = strings.TrimSpace(channelID)
	if channelID == "" {
		return fmt.Errorf("tuitui: channel id is required")
	}
	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))

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Ensure the markdown content is non-empty before calling; build a placeholder or error message if the body is empty.
  2. Check the upstream producer (agent output, template render) for why the content is blank.
  3. Skip the SendChannelPost call entirely when there is nothing to send.

Example fix

// before
p.SendChannelPost(ctx, chatID, renderTemplate(t), "") // renders to ""
// after
md := renderTemplate(t)
if strings.TrimSpace(md) == "" {
    md = "_(no content)_"
}
p.SendChannelPost(ctx, chatID, md, "")
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(markdown) == "" {
    return fmt.Errorf("cannot post: empty markdown")
}

Type guard

func hasContent(s string) bool { return strings.TrimSpace(s) != "" }

Try / catch

if err := p.SendChannelPost(ctx, chID, md, parent); err != nil && strings.Contains(err.Error(), "markdown is required") {
    log.Warn("skipping empty post")
}

Prevention

When it happens

Trigger: Calling SendChannelPost(ctx, channelID, "", parentID) or with whitespace-only markdown (e.g. "\n ").

Common situations: An agent produced empty output and the caller forwarded it verbatim; a template render that failed silently and yielded an empty string; stripping formatting removed all content.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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