Tencent/WeKnora · error
failed to upload file to OBS: %w
Error message
failed to upload file to OBS: %w
What it means
OBS PutObject failed while uploading the opened multipart file (with default or octet-stream content type) to the generated object key, so the file was not stored; permissions, quota, or connectivity failures are wrapped in the cause.
Source
Thrown at internal/application/service/file/obs.go:182
return "", fmt.Errorf("failed to open file: %w", err)
}
defer src.Close()
contentType := file.Header.Get("Content-Type")
if contentType == "" {
contentType = "application/octet-stream"
}
_, err = s.client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(s.bucketName),
Key: aws.String(objectKey),
Body: src,
ContentLength: aws.Int64(file.Size),
ContentType: aws.String(contentType),
// ACL: "private",
})
if err != nil {
return "", fmt.Errorf("failed to upload file to OBS: %w", err)
}
prefix := s.getPrifix()
if s.proxyDomain != "" {
return fmt.Sprintf("%s%s", prefix, objectKey), nil
}
return fmt.Sprintf("%s%s/%s", prefix, s.bucketName, objectKey), nil
}
func (s *obsFileService) GetFile(ctx context.Context, filePath string) (io.ReadCloser, error) {
objectKey, err := s.parseObsFilePath(filePath)
if err != nil {
return nil, err
}
output, err := s.client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(s.bucketName),
Key: aws.String(objectKey),
})View on GitHub (pinned to 988cbb0330)
Solutions
- Unwrap the error and check its code: credentials (SignatureDoesNotMatch/AccessDenied) vs network vs NoSuchBucket
- Verify endpoint, region, bucketName and AK/SK in the OBS service config
- Confirm the bucket exists and the credentials have s3:PutObject permission
- For transient network errors (timeouts, connection reset), retry with backoff; make SaveFile idempotent by generating a new objectKey per attempt
Example fix
// before
if err != nil { return "", fmt.Errorf("failed to upload file to OBS: %w", err) }
// after
if err != nil {
var ae smithy.APIError
if errors.As(err, &ae) && (ae.ErrorCode() == "AccessDenied" || ae.ErrorCode() == "SignatureDoesNotMatch") {
return "", fmt.Errorf("obs credentials/permissions problem: %w", err)
}
if isRetryableNetErr(err) {
return s.SaveFile(ctx, tenantID, knowledgeID, file) // new objectKey, retry once
}
return "", fmt.Errorf("failed to upload file to OBS: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
if endpoint == "" || bucketName == "" || accessKey == "" || secretKey == "" {
return errors.New("OBS config incomplete before SaveFile")
} Try / catch
path, err := svc.SaveFile(ctx, tenantID, kid, fh)
if err != nil {
var retryable interface{ RetryableError() bool }
if errors.As(err, &retryable) && retryable.RetryableError() {
path, err = svc.SaveFile(ctx, tenantID, kid, fh) // new objectKey per attempt
}
if err != nil {
return fmt.Errorf("obs upload failed: %w", err)
}
} Prevention
- Pre-flight the bucket and credentials at startup (HeadBucket)
- Grant least-privilege s3:PutObject on the app's prefix
- Use https endpoints with correct region; keep clock in sync for signatures
When it happens
Trigger: PutObject called with Body=src, ContentLength and ContentType; fails on network errors, invalid/expired credentials, missing write permission on the bucket, wrong region/endpoint, or content-length mismatch on the reader.
Common situations: Wrong OBS endpoint or region in config; IAM/AK-SK lacking PutObject permission; VPC endpoint or firewall blocking traffic; intermittent network failure on large uploads; clock skew breaking signature.
Related errors
- failed to get file from OBS: %w
- failed to copy file in OBS: %w
- failed to upload bytes to OBS: %w
- failed to upload bytes to S3: %w
- failed to delete file from OBS: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/c015e388ae5a433d.
Report an issue: GitHub.