juicedata/juicefs · error

json: %s

Error message

json: %s

What it means

When a volume is re-formatted (the format setting already exists), the stored format JSON is unmarshaled to compare old vs new settings. If the stored 'format' setting is not valid JSON, json.Unmarshal fails and the error is wrapped as 'json: %s'.

Source

Thrown at pkg/meta/sql.go:633

func (m *dbMeta) doInit(format *Format, force bool) error {
	if err := m.syncAllTables(); err != nil {
		return err
	}
	var s = setting{Name: "format"}
	var ok bool
	err := m.simpleTxn(Background(), func(ses *xorm.Session) (err error) {
		ok, err = ses.Get(&s)
		return err
	})
	if err != nil {
		return err
	}

	if ok {
		var old Format
		err = json.Unmarshal([]byte(s.Value), &old)
		if err != nil {
			return fmt.Errorf("json: %s", err)
		}
		if !old.DirStats && format.DirStats {
			// remove dir stats as they are outdated
			err = m.txn(func(s *xorm.Session) error {
				_, err := s.Where("TRUE").Delete(new(dirStats))
				if err != nil {
					return err
				}
				m.genLog(Background(), s, time.Now().UnixNano(), "INIT_ENABLE_DIRSTATS()")
				return nil
			})
			if err != nil {
				return errors.Wrap(err, "drop table dirStats")
			}
		}
		if !old.UserGroupQuota && format.UserGroupQuota {
			// remove user group quota as they are outdated
			err = m.txn(func(s *xorm.Session) error {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Inspect the setting row: SELECT value FROM <prefix>setting WHERE name='format'; and check for corruption
  2. Restore the volume format from a known-good backup (juicefs dump metadata output)
  3. Delete the corrupted setting row and re-run juicefs format with the original format options
  4. Recover from juicefs backup metadata if available
Defensive patterns

Strategy: validation

Validate before calling

// Before re-formatting, verify the stored format is valid JSON
row := db.QueryRow("SELECT value FROM setting WHERE name='format'")
var v string; row.Scan(&v)
var f map[string]any
if json.Unmarshal([]byte(v), &f) != nil { /* restore from backup before formatting */ }

Try / catch

defer func() {
    if r := recover(); r != nil { log.Fatalf("format corrupt: %v", r) }
}()

Prevention

When it happens

Trigger: juicefs format with an existing volume whose jfs.format setting row in the setting table is corrupted, truncated, or was written by a incompatible/older tool.

Common situations: Manual editing of the settings table; partial write from a crashed format; restoring metadata from a damaged backup; someone overwrote the setting value.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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