larksuite/cli · error

part %q is not an inline MIME part

Error message

part %q is not an inline MIME part

What it means

Guard in replaceInline: the resolved MIME part exists but is not an inline part (wrong disposition/content type), so it cannot be replaced by an inline image.

Source

Thrown at shortcuts/mail/draft/patch.go:677

		}
	}
	container.Children = append(container.Children, inline)
	container.Dirty = true
	return container, nil
}

func addInline(dctx *DraftCtx, snapshot *DraftSnapshot, path, cid, fileName, contentType string) error {
	_, err := loadAndAttachInline(dctx, snapshot, path, cid, fileName, nil)
	return err
}

func replaceInline(dctx *DraftCtx, snapshot *DraftSnapshot, partID, path, cid, fileName, contentType string) error {
	part := findPart(snapshot.Body, partID)
	if part == nil {
		return fmt.Errorf("inline part %q not found", partID)
	}
	if !isInlinePart(part) {
		return fmt.Errorf("part %q is not an inline MIME part", partID)
	}
	info, err := dctx.FIO.Stat(path)
	if err != nil {
		return err
	}
	if err := checkSnapshotAttachmentLimit(snapshot, info.Size(), part); err != nil {
		return err
	}
	f, err := dctx.FIO.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	content, err := io.ReadAll(f)
	if err != nil {
		return err
	}
	if strings.TrimSpace(fileName) == "" {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Re-fetch the draft and pick a partID whose Content-Disposition is inline
  2. Use the regular attachment-replace operation for non-inline parts
  3. If the part should be inline, remove it and re-add it as an inline image

Example fix

// before
--replace-inline part_id=att_1   # att_1 is a normal attachment
// after
--replace-attachment part_id=att_1 --path ./new.png
Defensive patterns

Strategy: type-guard

Validate before calling

snap, _ := draftGet(draftID)
p := findPart(snap.Body, partID)
if p != nil && (p.ContentDisposition != "inline") {
    // route to the attachment-replace operation instead
}

Type guard

func isInline(p *Part) bool {
    return p != nil && isInlinePart(p)
}

Try / catch

if err := replaceInline(...); err != nil {
    if strings.Contains(err.Error(), "not an inline MIME part") {
        // switch to replace-attachment path
    }
}

Prevention

When it happens

Trigger: applyOp -> replaceInline targeting a regular attachment part or the root part instead of an inline image part.

Common situations: Using an attachment partID with the inline-replace flag; draft mixes attachments and inline images and the wrong ID was picked; part was converted between attachment and inline by a previous edit.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/af955566e4f3c049. Report an issue: GitHub.