juicedata/juicefs · error

json: %s

Error message

json: %s

What it means

In doInit, after resolving/updating the volume format, JuiceFS re-serializes it with json.MarshalIndent to persist a human-readable copy in Redis. If marshaling fails, this "json: %s" error is returned (pkg/meta/redis.go:377). Marshal of a plain Format struct essentially cannot fail in practice, so hitting this indicates a deeply anomalous state (e.g., unsupported value slipped into the struct).

Source

Thrown at pkg/meta/redis.go:377

			// remove user group quota as they are outdated
			_, err := m.rdb.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
				pipe.Del(ctx, m.userQuotaKey(), m.userQuotaUsedSpaceKey(), m.userQuotaUsedInodesKey(),
					m.groupQuotaKey(), m.groupQuotaUsedSpaceKey(), m.groupQuotaUsedInodesKey())
				m.genLog(ctx, pipe, time.Now(), "INIT_ENABLE_USERGROUPQUOTA()")
				return nil
			})
			if err != nil {
				return errors.Wrap(err, "remove user group quota")
			}
		}
		if err = format.update(&old, force); err != nil {
			return errors.Wrap(err, "update format")
		}
	}

	data, err := json.MarshalIndent(format, "", "")
	if err != nil {
		return fmt.Errorf("json: %s", err)
	}
	ts := time.Now().Unix()
	attr := &Attr{
		Typ:    TypeDirectory,
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Nlink:  2,
		Length: 4 << 10,
		Parent: RootInode,
	}
	if format.TrashDays > 0 {
		attr.Mode = 0555
		if err = m.rdb.SetNX(ctx, m.inodeKey(TrashInode), m.marshal(attr), 0).Err(); err != nil {
			return err
		}
	}
	if err = m.rdb.Set(ctx, m.setting(), data, 0).Err(); err != nil {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. If running a patched/custom build, check recently added Format fields for unsupported JSON types (chan, func, complex, NaN floats).
  2. Retry the format command once — transient memory/allocator issues are effectively the only other cause.
  3. If it reproduces on a stock build, file a bug with the full error string and version (juicefs --version).

Example fix

// before (hypothetical patched Format)
type Format struct {
    Name string
    Hook func(string) // not JSON-marshalable
}
// after
type Format struct {
    Name string
    HookName string // marshalable representation
}
Defensive patterns

Strategy: try-catch

Try / catch

if err := initFormat(...); err != nil {
    if strings.HasPrefix(err.Error(), "json: ") {
        // practically indicates a non-marshalable field; treat as a bug,
        // report with juicefs --version and the full error string
    }
    return err
}

Prevention

When it happens

Trigger: json.MarshalIndent(format, ...) returns an error while initializing the volume — practically only if the Format struct contains a value that cannot be marshaled (unsupported type such as a channel/func or a NaN-ish number introduced by modified or patched code).

Common situations: Custom/patched JuiceFS builds that added a field of an unmarshalable type to Format; otherwise essentially never seen in stock builds — report as a bug if encountered.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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