juicedata/juicefs · warning

expect owner nobody but got %s

Error message

expect owner nobody but got %s

What it means

Verification failure in the 'change owner/group' case: after Chown to 'nobody', Head reports the object's Owner is still not 'nobody'. This means the ownership change did not take effect (silently ignored by the backend) or the metadata read is stale. It only fires when the object metadata is of type object.File (backends without File metadata skip the check).

Source

Thrown at cmd/objbench.go:1105

				return fmt.Errorf("the content of the multipart upload file is incorrect")
			}
			return nil
		}
		return utils.ErrNotSUP
	})

	funFSCase("change owner/group", func() error {
		if (strings.HasPrefix(blob.String(), "file://") || strings.HasPrefix(blob.String(), "jfs://")) && os.Getuid() != 0 {
			return errors.New("root required")
		}
		if err := fi.Chown(key, "nobody", groupName); err != nil {
			return fmt.Errorf("failed to chown object %s", err)
		}
		if objInfo, err := blob.Head(ctx, key); err != nil {
			return fmt.Errorf("failed to head object %s", err)
		} else if info, ok := objInfo.(object.File); ok {
			if info.Owner() != "nobody" {
				return fmt.Errorf("expect owner nobody but got %s", info.Owner())
			}
			if info.Group() != groupName {
				return fmt.Errorf("expect group %s but got %s", groupName, info.Group())
			}
		}
		return nil
	})

	funFSCase("change permission", func() error {
		if err := fi.Chmod(key, 0777); err != nil {
			return err
		}
		if objInfo, err := blob.Head(ctx, key); err != nil {
			return fmt.Errorf("failed to head object %s", err)
		} else if info, ok := objInfo.(object.File); ok {
			if info.Mode()&0xFFF != 0777 {
				return fmt.Errorf("expect mode %o but got %o", 0777, info.Mode())
			}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Verify the backend actually persists chown (test manually with `chown` + `ls -l`).
  2. Run as root — non-root chown may be silently dropped or fail in ways the check exposes.
  3. Invalidate/disable metadata caches between Chown and Head.
  4. Skip the ownership case for backends that don't support owner metadata.
Defensive patterns

Strategy: type-guard

Validate before calling

if objInfo, err := blob.Head(ctx, key); err == nil {
	if _, ok := objInfo.(object.File); !ok {
		return utils.ErrNotSUP // backend has no owner metadata to verify
	}
}

Type guard

func asFile(o object.ObjectMetadata) (object.File, bool) {
	f, ok := o.(object.File)
	return f, ok
}

Prevention

When it happens

Trigger: fi.Chown succeeded but info.Owner() != "nobody" in the subsequent Head: the backend accepted but ignored the chown, ownership mapping is not persisted, or a stale/cached metadata response was returned.

Common situations: Backends that emulate File metadata but don't persist owner changes, FUSE mounts where only root can chown yet the call silently no-ops, cached Head results on gateway/proxy layers.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/19c1ede1296cd1e5. Report an issue: GitHub.