chenhg5/cc-connect · error

tuitui: upload file: %w

Error message

tuitui: upload file: %w

What it means

SendFile uploads the file (or image, depending on detected type) via uploadMedia and wraps any upload failure as "tuitui: upload file: %w". Like the image path, it isolates the media-upload phase from message delivery. The wrapped error contains the true cause.

Source

Thrown at platform/tuitui/tuitui.go:257

	if err != nil {
		return err
	}
	return p.sendMediaID(ctx, rctx, mediaID, name, true)
}

func (p *Platform) SendFile(ctx context.Context, replyCtx any, file core.FileAttachment) error {
	name := file.FileName
	if name == "" {
		name = "file"
	}
	isImage := strings.HasPrefix(file.MimeType, "image/")
	mediaType := "file"
	if isImage {
		mediaType = "image"
	}
	mediaID, _, err := p.uploadMedia(ctx, file.Data, file.MimeType, name, mediaType)
	if err != nil {
		return fmt.Errorf("tuitui: upload file: %w", err)
	}
	rctx, err := requireReplyContext(replyCtx)
	if err != nil {
		return err
	}
	return p.sendMediaID(ctx, rctx, mediaID, name, isImage)
}

func (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {
	parts := strings.SplitN(sessionKey, ":", 3)
	if len(parts) < 2 || parts[0] != "tuitui" {
		return nil, fmt.Errorf("tuitui: invalid session key %q", sessionKey)
	}
	chatID := parts[1]
	if chatID == "" {
		return nil, fmt.Errorf("tuitui: invalid session key %q", sessionKey)
	}
	return replyContext{chatID: chatID, chatType: guessChatType(chatID)}, nil

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Unwrap the error to identify the root cause (auth vs size vs network) and address it.
  2. Check file size against the platform limit and compress/split if necessary before sending.
  3. Verify app credentials and network access to the upload endpoint; retry transient failures with backoff.

Example fix

// before
err := p.SendFile(ctx, rctx, core.FileData{FileName: "build.log", Data: data, MimeType: ""})
// after
if len(data) == 0 {
    return fmt.Errorf("refusing to send empty file")
}
err := p.SendFile(ctx, rctx, core.FileData{FileName: "build.log", Data: data, MimeType: "text/plain"})
Defensive patterns

Strategy: try-catch

Validate before calling

if len(file.Data) == 0 || file.FileName == "" || len(file.Data) > maxUploadSize {
    return fmt.Errorf("file not uploadable")
}

Type guard

func sendableFile(f core.FileData) bool {
    return len(f.Data) > 0 && strings.TrimSpace(f.FileName) != ""
}

Try / catch

if err := p.SendFile(ctx, rctx, f); err != nil {
    log.Error("file upload failed", "cause", errors.Unwrap(err))
}

Prevention

When it happens

Trigger: Calling SendFile with file.Data that uploadMedia rejects: bad or expired credentials, file exceeding size limits, wrong/empty MimeType or filename, network failure to the media endpoint.

Common situations: Sharing large logs or build artifacts above TuiTui's upload cap; media API outage; app secret rotated so auth fails; empty file passed from a failed read upstream.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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