juicedata/juicefs · warning
skip special file %s for jfs: %w
Error message
skip special file %s for jfs: %w
What it means
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.
Source
Thrown at cmd/object.go:128
_, _ = f.Seek(ctx, off, io.SeekStart)
}
if limit <= 0 {
limit = 1 << 62
}
return &jFile{f, limit}, nil
}
var bufPool = sync.Pool{
New: func() interface{} {
buf := make([]byte, 128<<10)
return &buf
},
}
func (j *juiceFS) Put(rCtx context.Context, key string, in io.Reader, getters ...object.AttrGetter) (err error) {
ctx := meta.WrapWithoutCancel(rCtx, pid, uid, []uint32{gid})
if vfs.IsSpecialName(key) {
return fmt.Errorf("skip special file %s for jfs: %w", key, utils.ErrSkipped)
}
p := j.path(key)
if strings.HasSuffix(p, "/") {
eno := j.jfs.MkdirAll(ctx, p, 0777, j.umask)
return toError(eno)
}
var tmp string
if object.PutInplace {
tmp = p
} else {
name := path.Base(p)
if len(name) > 200 {
name = name[:200]
}
tmp = object.TmpFilePath(p, name)
defer func() {
if err != nil {
if e := j.jfs.Delete(ctx, tmp); e != 0 && !errors.Is(e, syscall.ENOENT) {View on GitHub (pinned to c9a67b23e8)
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.
Example fix
// before
err := store.Put(ctx, key, reader) // key == ".stats" -> error
// after
if vfs.IsSpecialName(key) {
return utils.ErrSkipped // skip intentionally
}
err := store.Put(ctx, key, reader) Defensive patterns
Strategy: validation
Validate before calling
if vfs.IsSpecialName(key) {
return utils.ErrSkipped // skip before calling Put
} Try / catch
err := store.Put(ctx, key, reader)
if errors.Is(err, utils.ErrSkipped) {
log.Infof("skipped reserved file %s", key)
return nil
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/3c0ee2265ba00274.
Report an issue: GitHub.