{"record":{"id":"bf338be6b137d27c","repo":"juicedata/juicefs","slug":"begin-upload-s-w","errorCode":null,"errorMessage":"begin upload %s: %w","messagePattern":"begin upload (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/object/storj.go","lineNumber":164,"sourceCode":"\tif !seekable {\n\t\treturn s.putOnce(ctx, key, in)\n\t}\n\tstartPos, err := rs.Seek(0, io.SeekCurrent)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"capture read position %s: %w\", key, err)\n\t}\n\treturn storjBackoff(ctx, func() error {\n\t\tif _, err := rs.Seek(startPos, io.SeekStart); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn s.putOnce(ctx, key, rs)\n\t})\n}\n\nfunc (s *storjClient) putOnce(ctx context.Context, key string, in io.Reader) error {\n\tupload, err := s.project.UploadObject(ctx, s.bucket, key, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"begin upload %s: %w\", key, err)\n\t}\n\tif _, err = io.Copy(upload, in); err != nil {\n\t\t_ = upload.Abort()\n\t\treturn fmt.Errorf(\"upload %s: %w\", key, err)\n\t}\n\tif err = upload.Commit(); err != nil {\n\t\t_ = upload.Abort()\n\t\treturn fmt.Errorf(\"commit upload %s: %w\", key, err)\n\t}\n\treturn nil\n}\n\nfunc (s *storjClient) Copy(ctx context.Context, dst, src string) error {\n\treturn storjBackoff(ctx, func() error {\n\t\t_, err := s.project.CopyObject(ctx, s.bucket, src, s.bucket, dst, nil)\n\t\treturn err\n\t})\n}","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/object/storj.go#L146-L182","documentation":"storjClient.putOnce starts a multipart-style upload via project.UploadObject; failure to begin the upload is wrapped as 'begin upload <key>' with %w preserving the Storj cause. This happens before any data is transferred, so it indicates the upload could not be initiated at all.","triggerScenarios":"project.UploadObject returns an error: bucket doesn't exist, invalid/revoked access grant, key invalid for Storj (e.g. invalid UTF-8 or disallowed), context cancelled, or satellite/network unreachable.","commonSituations":"Writing to a bucket that was deleted after mount; expired Storj access grant mid-session; uploading keys with characters Storj rejects; network partition to the satellite.","solutions":["Verify the bucket still exists and the access grant is valid; recreate bucket or regenerate the access grant.","Check the object key is valid (UTF-8, no NUL bytes) before calling Put.","Check network connectivity to the Storj satellite and retry; upstream the wrapped error (%w) for the precise cause."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"_, err := project.ListBuckets(ctx, &uplink.ListBucketsOptions{})\nif err != nil { return fmt.Errorf(\"storj project unreachable or bad grant: %v\", err) }","typeGuard":null,"tryCatchPattern":"err := storjBackoff(ctx, func() error { return client.Put(ctx, key, in) })\nif err != nil && strings.Contains(err.Error(), \"begin upload\") {\n    // check grant validity/bucket existence before next retry\n    return err\n}","preventionTips":["Keep access grants valid and rotate them before expiry.","Verify bucket existence after any out-of-band bucket management.","Monitor satellite connectivity; rely on storjBackoff for transient faults but alert on persistent begin-upload failures."],"tags":["storj","upload","network"],"backgroundTag":"api-request-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}