{"record":{"id":"3c0ee2265ba00274","repo":"juicedata/juicefs","slug":"skip-special-file-s-for-jfs-w","errorCode":null,"errorMessage":"skip special file %s for jfs: %w","messagePattern":"skip special file (.+?) for jfs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/object.go","lineNumber":128,"sourceCode":"\t\t_, _ = f.Seek(ctx, off, io.SeekStart)\n\t}\n\tif limit <= 0 {\n\t\tlimit = 1 << 62\n\t}\n\treturn &jFile{f, limit}, nil\n}\n\nvar bufPool = sync.Pool{\n\tNew: func() interface{} {\n\t\tbuf := make([]byte, 128<<10)\n\t\treturn &buf\n\t},\n}\n\nfunc (j *juiceFS) Put(rCtx context.Context, key string, in io.Reader, getters ...object.AttrGetter) (err error) {\n\tctx := meta.WrapWithoutCancel(rCtx, pid, uid, []uint32{gid})\n\tif vfs.IsSpecialName(key) {\n\t\treturn fmt.Errorf(\"skip special file %s for jfs: %w\", key, utils.ErrSkipped)\n\t}\n\tp := j.path(key)\n\tif strings.HasSuffix(p, \"/\") {\n\t\teno := j.jfs.MkdirAll(ctx, p, 0777, j.umask)\n\t\treturn toError(eno)\n\t}\n\tvar tmp string\n\tif object.PutInplace {\n\t\ttmp = p\n\t} else {\n\t\tname := path.Base(p)\n\t\tif len(name) > 200 {\n\t\t\tname = name[:200]\n\t\t}\n\t\ttmp = object.TmpFilePath(p, name)\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tif e := j.jfs.Delete(ctx, tmp); e != 0 && !errors.Is(e, syscall.ENOENT) {","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/object.go#L110-L146","documentation":"The JuiceFS object-storage adapter (jfs backend for gateway/sync) refuses Put operations whose key resolves to a JuiceFS internal special file (vfs.IsSpecialName), returning the error wrapped with utils.ErrSkipped so sync/gateway can skip it. JuiceFS reserves names like .accesslog, .stats, .config etc. for its control files, so external writes to them must be rejected.","triggerScenarios":"objectStorage.Put(key, ...) — directly or via UploadPartStream — where key is or lives under a reserved internal name (e.g. putting an object literally named '.stats' or '.accesslog' via the S3 gateway or `juicefs sync` into a jfs target).","commonSituations":"Syncing a directory that contains files named .accesslog/.stats/.config into a jfs:// target; an S3 client of the gateway PUTting an object with a reserved name; listing a JuiceFS mount recursively and re-uploading its control files.","solutions":["Rename or exclude the reserved-name file from the source of the sync/put (use sync --exclude patterns).","If produced by the gateway, have the client use a different object key.","Handle utils.ErrSkipped in your caller — it signals skip, not fatal failure.","Check vfs.IsSpecialName for the list of reserved names and avoid creating such files upstream."],"exampleFix":"// before\nerr := store.Put(ctx, key, reader) // key == \".stats\" -> error\n// after\nif vfs.IsSpecialName(key) {\n    return utils.ErrSkipped // skip intentionally\n}\nerr := store.Put(ctx, key, reader)","handlingStrategy":"validation","validationCode":"if vfs.IsSpecialName(key) {\n    return utils.ErrSkipped // skip before calling Put\n}","typeGuard":null,"tryCatchPattern":"err := store.Put(ctx, key, reader)\nif errors.Is(err, utils.ErrSkipped) {\n    log.Infof(\"skipped reserved file %s\", key)\n    return nil\n}","preventionTips":["Exclude reserved names (.stats, .accesslog, .config, ...) in sync with --exclude.","Avoid creating files whose names match vfs.IsSpecialName in source directories.","Check errors.Is(err, utils.ErrSkipped) instead of treating it as fatal.","When exposing the S3 gateway, validate keys client-side."],"tags":["juicefs","special-file","s3-gateway","sync"],"backgroundTag":"unsupported-operation","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"}