argoproj/argo-workflows · error

get Rel path from %s to %s error: %w

Error message

get Rel path from %s to %s error: %w

What it means

When downloading an OSS 'directory' artifact, GetOssDirectory (workflow/artifacts/oss/oss.go:556) computes each listed object key's path relative to the directory prefix via filepath.Rel so it can recreate the tree under the local destination. If filepath.Rel fails — it cannot produce a relative path, e.g. when the object key cannot be reached from the base prefix — the error is wrapped as 'get Rel path from %s to %s error: %w'.

Source

Thrown at workflow/artifacts/oss/oss.go:558

	if err != nil {
		return false, err
	}
	if len(rst.CommonPrefixes)+len(rst.Objects) > 0 {
		return true, nil
	}
	return false, nil
}

// GetOssDirectory download an OSS "directory" to local path
func GetOssDirectory(ctx context.Context, bucket *oss.Bucket, objectName, path string) error {
	files, err := ListOssDirectory(ctx, bucket, objectName)
	if err != nil {
		return err
	}
	for _, f := range files {
		innerName, err := filepath.Rel(objectName, f)
		if err != nil {
			return fmt.Errorf("get Rel path from %s to %s error: %w", f, objectName, err)
		}
		fpath := filepath.Join(path, innerName)
		if strings.HasSuffix(f, "/") {
			err = os.MkdirAll(fpath, 0o700)
			if err != nil {
				return fmt.Errorf("mkdir %s error: %w", fpath, err)
			}
			continue
		}
		dirPath := filepath.Dir(fpath)
		err = os.MkdirAll(dirPath, 0o700)
		if err != nil {
			return fmt.Errorf("mkdir %s error: %w", dirPath, err)
		}

		err = bucket.GetObjectToFile(f, fpath)
		if err != nil {
			logging.RequireLoggerFromContext(ctx).WithFields(logging.Fields{"key": f, "path": fpath}).WithError(err).Warn(ctx, "failed to load object")

View on GitHub (pinned to 35bff19146)

Solutions

  1. Ensure the objectName passed to GetOssDirectory is exactly the prefix used for listing, with a trailing '/' for directory keys (ListOssDirectory normalizes it, so pass the same original key).
  2. Verify listed keys all begin with the objectName prefix; if they do not, fix the caller/listing logic rather than the path math.
  3. If keys may escape the base (contain '..'), sanitize or reject them before calling GetOssDirectory.
  4. On Windows, check the keys use consistent separators ('/' vs '\\') acceptable to filepath.Rel.

Example fix

// before
err := GetOssDirectory(ctx, bucket, "my-dir", "/tmp/art") // listing keys: "other/x.txt"
// after
err := GetOssDirectory(ctx, bucket, "my-dir/", "/tmp/art") // keys "my-dir/x.txt" rel correctly
Defensive patterns

Strategy: validation

Validate before calling

if !strings.HasPrefix(f, strings.TrimSuffix(objectName, "/")+"/") {
    return fmt.Errorf("key %q is not under prefix %q; refusing Rel", f, objectName)
}

Prevention

When it happens

Trigger: Calling GetOssDirectory with an objectName (base) that does not prefix the listed file keys. Practically this happens when the bucket listing returns keys outside the requested prefix — for example the base objectName lacks the trailing '/' that ListOssDirectory normalizes on, or the caller passes a different/mutated key than the one used to list, so keys like 'a/b/c.txt' are Rel'd against base 'a' or an unrelated path.

Common situations: Manually invoking the artifact driver with a key missing its trailing slash; a custom driver/plugin passing an absolute vs relative mismatch; OSS keys containing '..' or symlink-like segments that make filepath.Rel return an error on Windows; writing tests that call GetOssDirectory with an objectName that doesn't match the stubbed listing.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/dde95781cc3a00c7. Report an issue: GitHub.