larksuite/cli · error

resolve save path: %w

Error message

resolve save path: %w

What it means

Wraps a validation failure from FileIO.ResolvePath while resolving the save path. The provider rejected the path — typical causes are path traversal, symlink escape, or otherwise invalid target — and the cause is preserved via %w. It guards that saves stay inside the validated workspace.

Source

Thrown at shortcuts/common/runner.go:655

		if ctx != nil {
			c = ctx.ctx
		}
		return p.ResolveFileIO(c)
	}
	return nil
}

// ResolveSavePath resolves a relative path to a validated absolute path via
// FileIO.ResolvePath. It returns an error if no FileIO provider is registered
// or if the path fails validation (e.g. traversal, symlink escape).
func (ctx *RuntimeContext) ResolveSavePath(path string) (string, error) {
	fio := ctx.FileIO()
	if fio == nil {
		return "", fmt.Errorf("no file I/O provider registered")
	}
	resolved, err := fio.ResolvePath(path)
	if err != nil {
		return "", fmt.Errorf("resolve save path: %w", err)
	}
	if resolved == "" {
		return "", fmt.Errorf("resolve save path: empty result for %q", path)
	}
	return resolved, nil
}

// WrapOpenError matches a FileIO.Open/Stat error and wraps it with the
// caller-provided message prefix.
func WrapOpenError(err error, pathMsg, readMsg string) error {
	if err == nil {
		return nil
	}
	if errors.Is(err, fileio.ErrPathValidation) {
		return fmt.Errorf("%s: %w", pathMsg, err)
	}
	return fmt.Errorf("%s: %w", readMsg, err)
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Fix the input path so it resolves inside the allowed save root (remove ".." or symlink hops)
  2. Inspect the wrapped cause to see which validation failed and adjust accordingly
  3. Use runtime.ValidatePath() on candidate paths ahead of time, or let ResolveSavePath normalize by passing a plain relative filename

Example fix

// before
p, err := ctx.ResolveSavePath("../../etc/out.json")
// after
p, err := ctx.ResolveSavePath("out.json") // resolves inside validated save root
Defensive patterns

Strategy: validation

Validate before calling

// Reject obviously escaping paths before calling:
if strings.Contains(filepath.ToSlash(path), "..") {
	return fmt.Errorf("path must stay inside the save directory")
}
out, err := ctx.ResolveSavePath(path)

Try / catch

out, err := ctx.ResolveSavePath(path)
if err != nil {
	var ve *errs.ValidationError
	if errors.As(errors.Unwrap(err), &ve) {
		return fmt.Errorf("invalid save path %q: %w", path, err)
	}
	return err
}

Prevention

When it happens

Trigger: ctx.ResolveSavePath("../x") or any path failing ResolvePath validation: ".." escaping the base dir, symlinked paths resolving outside allowed roots, absolute paths in restricted modes, illegal characters.

Common situations: Users passing relative paths with ".." from a different working directory; saving into symlinked folders pointing outside the workspace; paths referencing other users' directories in shared setups.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


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