larksuite/cli · error

inline image %q: %w

Error message

inline image %q: %w

What it means

loadAndAttachInline failed at the first step: Stat on the local image path via the draft FileIO returned an error, wrapped as "inline image %q: %w". The file does not exist, is inaccessible, or the path is invalid in the current execution context (path resolution/validation happens before this point). The original Stat error is preserved as the cause.

Source

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

		MediaType:   "multipart/mixed",
		MediaParams: map[string]string{"boundary": boundary},
		Dirty:       true,
		Headers: []Header{
			{Name: "Content-Type", Value: mime.FormatMediaType("multipart/mixed", map[string]string{"boundary": boundary})},
		},
		Children: []*Part{original, attachment},
	}
	return nil
}

// loadAndAttachInline reads a local image file, validates its format,
// creates a MIME inline part, and attaches it to the snapshot's
// multipart/related container. If container is non-nil it is reused;
// otherwise the container is resolved from the snapshot.
func loadAndAttachInline(dctx *DraftCtx, snapshot *DraftSnapshot, path, cid, fileName string, container *Part) (*Part, error) {
	info, err := dctx.FIO.Stat(path)
	if err != nil {
		return nil, fmt.Errorf("inline image %q: %w", path, err)
	}
	if err := checkSnapshotAttachmentLimit(snapshot, info.Size(), nil); err != nil {
		return nil, err
	}
	f, err := dctx.FIO.Open(path)
	if err != nil {
		return nil, fmt.Errorf("inline image %q: %w", path, err)
	}
	defer f.Close()
	content, err := io.ReadAll(f)
	if err != nil {
		return nil, fmt.Errorf("inline image %q: %w", path, err)
	}
	name := fileName
	if strings.TrimSpace(name) == "" {
		name = filepath.Base(path)
	}
	detectedCT, err := filecheck.CheckInlineImageFormat(name, content)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Verify the image path exists and is readable from the CLI's execution context (use absolute paths).
  2. Resolve the path through the runtime's path validation (runtime.ValidatePath) so workspace-relative paths resolve correctly.
  3. Check file permissions and that the file lives inside the allowed workspace/execution scope.
  4. If running remotely or sandboxed, copy the image into the workspace the FileIO can access first.

Example fix

// before
addInline(ctx, snapshot, "./assets/logo.png", "logo", "")
// after: ensure absolute, existing path
path := "/work/project/assets/logo.png" // verified to exist
addInline(ctx, snapshot, path, "logo", "")
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil || info.IsDir() {
	return fmt.Errorf("inline image path unusable: %w", err)
}

Type guard

func fileReadable(path string) bool {
	info, err := os.Stat(path)
	return err == nil && !info.IsDir()
}

Try / catch

part, err := loadAndAttachInline(dctx, snapshot, path, cid, name, nil)
if err != nil {
	var perr *fs.PathError
	if errors.As(err, &perr) && errors.Is(perr, fs.ErrNotExist) {
		// fix path / copy file into workspace
	}
	return err
}

Prevention

When it happens

Trigger: Calling addInline or resolveLocalImgSrc with a path that does not exist, has a typo, is outside the allowed workspace, or the runtime lacks read permission — FIO.Stat(path) fails.

Common situations: Relative path used where an absolute path is expected; file deleted between HTML authoring and the inline-attach step; sandbox/remote execution where the CLI's FileIO cannot see the developer's local file; wrong working directory.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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