larksuite/cli · error

create directory: %w

Error message

create directory: %w

What it means

SaveResponse wraps failures from the FileIO Mkdir call when it needs to create the output directory for a saved API response. If the underlying error is a fileio.MkdirError, it is re-wrapped as 'create directory: %w' with the original cause preserved. This signals that the output path's parent directory could not be created, distinct from path-validation failures ('unsafe output path') and write failures ('cannot write file').

Source

Thrown at internal/client/response.go:220

}

// ── File saving ──

// SaveResponse writes an API response body to the given outputPath and returns metadata.
// It delegates to FileIO.Save for path validation and atomic write; fio must not be nil.
func SaveResponse(fio fileio.FileIO, resp *larkcore.ApiResp, outputPath string) (map[string]interface{}, error) {
	result, err := fio.Save(outputPath, fileio.SaveOptions{
		ContentType:   resp.Header.Get("Content-Type"),
		ContentLength: int64(len(resp.RawBody)),
	}, bytes.NewReader(resp.RawBody))
	if err != nil {
		var me *fileio.MkdirError
		var we *fileio.WriteError
		switch {
		case errors.Is(err, fileio.ErrPathValidation):
			return nil, fmt.Errorf("unsafe output path: %w", err)
		case errors.As(err, &me):
			return nil, fmt.Errorf("create directory: %w", err)
		case errors.As(err, &we):
			return nil, fmt.Errorf("cannot write file: %w", err)
		default:
			return nil, fmt.Errorf("cannot write file: %w", err)
		}
	}

	resolvedPath, err := fio.ResolvePath(outputPath)
	if err != nil || resolvedPath == "" {
		resolvedPath = outputPath
	}
	return map[string]interface{}{
		"saved_path":   resolvedPath,
		"size_bytes":   result.Size(),
		"content_type": resp.Header.Get("Content-Type"),
	}, nil
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Check permissions on the nearest existing ancestor of outputPath and create the directory manually (mkdir -p) or run with write access
  2. Verify no regular file exists at the directory segment of outputPath; rename or remove it
  3. If running in a scoped/sandboxed environment, save inside the FileIO-allowed tree (e.g. use runtime.ResolveSavePath)
  4. Inspect the wrapped cause (%v / errors.Unwrap) for the exact OS error and act on it

Example fix

// before
client.SaveResponse(resp, "/root/outputs/response.json") // permission denied
// after
client.SaveResponse(resp, filepath.Join(os.TempDir(), "lark-outputs", "response.json"))
Defensive patterns

Strategy: try-catch

Validate before calling

if st, err := os.Stat(filepath.Dir(outputPath)); err == nil && !st.IsDir() {
    return fmt.Errorf("%s exists and is not a directory", filepath.Dir(outputPath))
}

Type guard

var me *fileio.MkdirError
if errors.As(err, &me) { /* handle mkdir failure specifically */ }

Try / catch

path, err := client.SaveResponse(resp, outputPath)
if err != nil {
    var me *fileio.MkdirError
    if strings.HasPrefix(err.Error(), "create directory:") || errors.As(err, &me) {
        // fix directory creation: permissions, existing file, allowed tree
    }
    return err
}

Prevention

When it happens

Trigger: Calling SaveResponse (directly or via HandleResponse/saveAndPrint) with an outputPath whose directory cannot be created by the FileIO layer — e.g. permission denied on the parent, a non-directory file occupying the path segment, or filesystem errors on the host where FileIO runs.

Common situations: Saving to a path under a read-only directory, an output path colliding with an existing regular file (e.g. .../out exists as a file so .../out/part.json can't get a dir), sandboxed/CI filesystems denying writes, or a remote/scoped FileIO backend refusing mkdir outside its allowed tree.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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