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
- Inspect the wrapped cause (%w) in logs for the OSS error code — AccessDenied means fix RAM/RAM policy or credentials.
- Verify endpoint region matches the bucket's region and the bucket name is correct.
- If STS is used, re-issue/refresh the security token; expired tokens are not retried.
- For throttling/network codes, the built-in retry already runs — increase connectivity or check OSS status page.
- 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
- Match endpoint region to bucket region
- Grant oss:GetObject on the exact key prefix in RAM policy
- Rotate STS tokens before long workflow runs
- Run a preflight GetObjectMeta in canary tests
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
- failed get directory: %w
- CodeNotFound
- unable to open stream for blob %s: %w
- mkdir %s error: %w
- failed to test if %s/%s is a directory: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/8ceede11785bd730.
Report an issue: GitHub.