{"record":{"id":"d4f3083ac3d2f860","repo":"juicedata/juicefs","slug":"bucket-name-required","errorCode":null,"errorMessage":"bucket name required","messagePattern":"bucket name required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/object/dragonfly.go","lineNumber":536,"sourceCode":"\treturn generateListResult(objs, limit)\n}\n\n// newDragonfly creates a new dragonfly object storage.\nfunc newDragonfly(endpoint, accessKey, secretKey, token string) (ObjectStorage, error) {\n\tif !strings.Contains(endpoint, \"://\") {\n\t\tendpoint = fmt.Sprintf(\"http://%s\", endpoint)\n\t}\n\n\t// Parse the endpoint.\n\turi, err := url.Parse(endpoint)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tendpoint = uri.Scheme + \"://\" + uri.Host\n\tbucket := uri.Path\n\tif bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"bucket name required\")\n\t}\n\n\tif !strings.Contains(endpoint, \"://\") {\n\t\tendpoint = fmt.Sprintf(\"http://%s\", endpoint)\n\t}\n\n\tmode := WriteBack\n\tif value := uri.Query().Get(\"mode\"); value != \"\" {\n\t\tmode, err = strconv.Atoi(value)\n\t\tif err != nil || (mode != WriteBack && mode != AsyncWriteBack) {\n\t\t\treturn nil, fmt.Errorf(\"unexpected dragonfly mode: %s\", value)\n\t\t}\n\t}\n\n\tmaxReplicas := DefaultMaxReplicas\n\tif value := uri.Query().Get(\"maxReplicas\"); value != \"\" {\n\t\tmaxReplicas, err = strconv.Atoi(value)\n\t\tif err != nil || maxReplicas > MaxReplicasLimit || maxReplicas < 0 {","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/object/dragonfly.go#L518-L554","documentation":"newDragonfly parses the dragonfly:// endpoint URL and takes the URL path as the bucket name. If the URL has no path component (e.g. dragonfly://host:8000), there is no bucket to operate on, so construction fails immediately with this error. The Dragonfly client requires every operation to be scoped to a bucket under /buckets/<bucket>/.","triggerScenarios":"Constructing a dragonfly object storage via newDragonfly (registered as \"dragonfly\" scheme, e.g. during juicefs format/mount) with a URL lacking a path: \"dragonfly://host:8000\", \"http://host:8000\", or a URL with an empty path after parsing.","commonSituations":"Copy-pasting a dfdaemon address without appending the bucket name; environment-variable-driven endpoint configs where the bucket part is dropped; automation generating URLs from host-only values; confusion with other object storage clients where the bucket is passed separately.","solutions":["Append the bucket name to the URL path: use dragonfly://<host>/<bucket> instead of dragonfly://<host>.","If the endpoint comes from config or an env var, check it contains a non-empty path before passing it to the client.","For other schemes (e.g. s3://, oss://), ensure you are using the dragonfly scheme correctly — the bucket is the first path segment, not a query parameter."],"exampleFix":"// before\nendpoint := \"dragonfly://dfdaemon.example.com:8000\"\n// after\nendpoint := \"dragonfly://dfdaemon.example.com:8000/mybucket\"","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(endpoint)\nif u.Scheme == \"dragonfly\" && strings.Trim(u.Path, \"/\") == \"\" {\n    return errors.New(\"dragonfly URL requires a bucket: dragonfly://host/bucket\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include the bucket as the first path segment: dragonfly://host:8000/bucket.","Validate the endpoint in config loading before passing it to juicefs format/mount.","When generating URLs from host-only values, append the bucket explicitly.","Add a startup smoke test that constructs the client so config errors surface early."],"tags":["configuration","url","dragonfly","bucket"],"backgroundTag":"missing-required-argument","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}