{"record":{"id":"6940078123d735e7","repo":"juicedata/juicefs","slug":"errdirsuffix","errorCode":"errDirSuffix","errorMessage":"dir miss suffix '/'","messagePattern":"dir miss suffix '/'","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/sync/sync.go","lineNumber":1924,"sourceCode":"\tfor scanner.Scan() {\n\t\tkey := scanner.Text()\n\t\tif key == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\ttrimKey := strings.TrimRightFunc(key, unicode.IsSpace)\n\t\tif trimKey != key {\n\t\t\tlogger.Infof(\"found a prefix with a space character:%q\", key)\n\t\t}\n\t\tprefixs <- trimKey\n\t}\n\tclose(prefixs)\n\n\twg.Wait()\n\tlistedPrefix.Done()\n\treturn nil\n}\n\nvar errDirSuffix = errors.New(\"dir miss suffix '/'\")\nvar ignoreFiles int64\n\nfunc produceSingleObject(tasks chan<- object.Object, src, dst object.ObjectStorage, key string, config *Config, checkpointMgr *CheckpointManager) error {\n\tobj, err := src.Head(ctx, key)\n\tif err != nil {\n\t\tif config.Links && (errors.Is(err, utils.ErrExtlink) || errors.Is(err, syscall.ENOTSUP) || errors.Is(err, os.ErrNotExist)) {\n\t\t\tif sl, ok := src.(object.SupportSymlink); ok {\n\t\t\t\tif target, e := sl.Readlink(key); e == nil {\n\t\t\t\t\tobj, err = object.NewSymlink(key, target), nil\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"readlink %s from %s: %w\", key, src, e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err != nil {\n\t\t\tlogger.Warnf(\"head %s from %s: %s\", key, src, err)\n\t\t\treturn err\n\t\t}","sourceCodeStart":1906,"sourceCodeEnd":1942,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/sync/sync.go#L1906-L1942","documentation":"errDirSuffix is returned by produceSingleObject (used by --files-from) when the input names a directory-like key that lacks a trailing '/'. Sync requires directory keys to end with '/' so it can treat them as directories rather than files.","triggerScenarios":"Running juicefs sync with --files-from where a line lists a directory without a trailing slash; keys computed from user lists that omit the suffix.","commonSituations":"Generating the files-from list with find/ls without appending '/' to directories; copying lists between systems with different directory conventions.","solutions":["Append '/' to directory entries in the --files-from list","Or pass the key through Head first: the sync code itself appends '/' when it sees errDirSuffix — normalize your list the same way","Exclude directories from the list if you only intend to sync files"],"exampleFix":"# before\nsubdir\n# after\nsubdir/","handlingStrategy":"validation","validationCode":"if isDir && !strings.HasSuffix(key, \"/\") {\n\tkey += \"/\" // normalize directory keys before --files-from\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate --files-from lists with directory trailing slashes (e.g. find -type d -exec printf '%s/\\n' {})","Validate list entries before starting sync","Exclude plain files when copying directory trees"],"tags":["sync","validation","directory"],"backgroundTag":"invalid-argument-format","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"}