argoproj/argo-workflows · error

failed to get file: %w

Error message

failed to get file: %w

What it means

OSS Load's GetObjectToFile failed with an error that is not NoSuchKey, so the driver cannot treat it as 'missing key'; it wraps it as 'failed to get file'. This covers all real transfer failures: auth errors, bucket/endpoint mismatch, network failure, permission denied, throttling.

Source

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

			if err != nil {
				return !isTransientOSSErr(ctx, err), err
			}
			bucket, err := osscli.Bucket(bucketName)
			if err != nil {
				return !isTransientOSSErr(ctx, err), err
			}
			objectName := inputArtifact.OSS.Key
			dirPath := filepath.Dir(path)
			err = os.MkdirAll(dirPath, 0o700)
			if err != nil {
				return false, fmt.Errorf("mkdir %s error: %w", dirPath, err)
			}
			origErr := bucket.GetObjectToFile(objectName, path)
			if origErr == nil {
				return true, nil
			}
			if !IsOssErrCode(origErr, "NoSuchKey") {
				return !isTransientOSSErr(ctx, origErr), fmt.Errorf("failed to get file: %w", origErr)
			}
			// If we get here, the error was a NoSuchKey. The key might be a oss "directory"
			isDir, err := IsOssDirectory(bucket, objectName)
			if err != nil {
				return !isTransientOSSErr(ctx, err), fmt.Errorf("failed to test if %s/%s is a directory: %w", bucketName, objectName, err)
			}
			if !isDir {
				// It's neither a file, nor a directory. Return the original NoSuchKey error
				return false, origErr
			}

			if err = GetOssDirectory(ctx, bucket, objectName, path); err != nil {
				return !isTransientOSSErr(ctx, err), fmt.Errorf("failed get directory: %w", err)
			}
			return true, nil
		})
	return err
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Inspect the wrapped cause (%w) in logs for the OSS error code — AccessDenied means fix RAM/RAM policy or credentials.
  2. Verify endpoint region matches the bucket's region and the bucket name is correct.
  3. If STS is used, re-issue/refresh the security token; expired tokens are not retried.
  4. For throttling/network codes, the built-in retry already runs — increase connectivity or check OSS status page.
  5. Confirm the pod's credentials actually grant oss:GetObject on the key.

Example fix

// before: endpoint in wrong region
oss:
  endpoint: http://oss-cn-beijing.aliyuncs.com
  bucket: my-hangzhou-bucket
// after
oss:
  endpoint: http://oss-cn-hangzhou.aliyuncs.com
  bucket: my-hangzhou-bucket
Defensive patterns

Strategy: retry

Validate before calling

// preflight: cheap HEAD-style existence + auth check
cli, err := oss.New(endpoint, ak, sk)
if err == nil {
	_, err = cli.Bucket(bucket).GetObjectMeta(key)
}
// non-nil err here predicts 'failed to get file' during Load

Type guard

import oerr "github.com/aliyun/aliyun-oss-go-sdk/oss"
func isOSSAccessDenied(err error) bool {
	var sr oerr.ServiceError
	return errors.As(err, &sr) && sr.Code == "AccessDenied"
}

Try / catch

err := driver.Load(ctx, art, path)
var isTransient bool
if errors.As(err, &boolErr{&isTransient}); !isTransient {
	// permanent (auth/permission): do not retry, fix credentials or key
} else {
	// retry with backoff
}

Prevention

When it happens

Trigger: bucket.GetObjectToFile(objectName, path) returns a non-NoSuchKey error: wrong credentials (AccessDenied), nonexistent bucket name, wrong endpoint region, oversized object, or transient network errors after retries are exhausted.

Common situations: Cross-region endpoint vs bucket mismatch; expired STS token mid-run; IAM/RAM policy without oss:GetObject; bucket names with typos; the underlying error is retried via waitutil.Backoff only if isTransientOSSErr says so, so persistent auth errors surface immediately.

Related errors


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