juicedata/juicefs · error

drop table dirStats

Error message

drop table dirStats

What it means

During `juicefs format` (doInit in the SQL metadata engine), when a volume previously had DirStats disabled and the new format enables it, all stale rows are deleted from the dirStats table inside a transaction. If that transactional DELETE fails (DB error, lock conflict, connection drop), the underlying database error is wrapped as "drop table dirStats" and format aborts.

Solutions

  1. Check DB connectivity and credentials, then retry `juicefs format`
  2. Verify the metadata DB user has DELETE privilege on the dirStats table
  3. Check DB error logs (wrapped error includes the cause) for lock timeouts/deadlocks and tune innodb_lock_wait_timeout or equivalent
  4. If corruption is suspected, take a metadata backup (`juicefs dump`) and inspect the dirStats table
Defensive patterns

Strategy: retry

Validate before calling

// before formatting, ensure connectivity
err := db.Ping()
if err != nil { return fmt.Errorf("metadata DB unreachable: %w", err) }

Try / catch

if err := juicefsFormat(url, name); err != nil && strings.Contains(err.Error(), "drop table dirStats") {
    // inspect wrapped cause, fix DB access/locks, then retry
}

Prevention

When it happens

Trigger: Running `juicefs format <sql-url> <name>` on an existing SQL (MySQL/Postgres/SQLite) volume whose stored format has DirStats=false while the new format has DirStats=true, and the DELETE FROM dirStats transaction fails due to a database error, lock timeout, or lost connection.

Common situations: Upgrading/re-formatting a volume to enable directory stats on a MySQL/Postgres server with lock waits or an unstable connection; DB user lacking DELETE privilege on the dirStats table; DB under heavy load causing deadlocks.

Related errors


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

Appendix: source

Thrown at pkg/meta/sql.go:646

	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 {
				_, err := s.Where("TRUE").Delete(new(userGroupQuota))
				if err != nil {
					return err
				}
				m.genLog(Background(), s, time.Now().UnixNano(), "INIT_ENABLE_USERGROUPQUOTA()")
				return nil
			})
			if err != nil {
				return errors.Wrap(err, "drop table userGroupQuota")
			}
		}
		if err = format.update(&old, force); err != nil {
			return errors.Wrap(err, "update format")

View on GitHub (pinned to c9a67b23e8)