juicedata/juicefs · error

only %d records inserted

Error message

only %d records inserted

What it means

During backup loading (sql_bak.go), records are inserted into the SQL metadata engine in batches inside a transaction. xorm's Insert returns the number of rows affected; if it differs from the batch size, JuiceFS treats the insert as incomplete and fails with this error to avoid silently writing a partial backup. It indicates a partially-failed multi-row insert that the driver did not report as an error.

Source

Thrown at pkg/meta/sql_bak.go:861

	for _, st := range stats {
		rows = append(rows, &dirStats{
			Inode:      Ino(st.Inode),
			DataLength: st.DataLength,
			UsedInodes: st.UsedInodes,
			UsedSpace:  st.UsedSpace,
		})
	}
	return m.insertRows(rows)
}

func (m *dbMeta) insertRows(beans []interface{}) error {
	batch := m.getTxnBatchNum()
	for len(beans) > 0 {
		bs := min(batch, len(beans))
		err := m.txn(func(s *xorm.Session) error {
			n, err := s.Insert(beans[:bs])
			if err == nil && int(n) != bs {
				err = fmt.Errorf("only %d records inserted", n)
			}
			return err
		})
		if err != nil {
			logger.Errorf("Write %d beans: %s", bs, err)
			return err
		}
		beans = beans[bs:]
	}
	return nil
}

func (m *dbMeta) prepareLoad(ctx Context, opt *LoadOption) error {
	opt.check()
	if err := m.checkAddr(); err != nil {
		return err
	}
	if err := m.syncAllTables(); err != nil {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Retry the load; if it recurs, check the target DB's affected-rows semantics and driver DSN flags (e.g. enable CLIENT_FOUND_ROWS on MySQL).
  2. Verify the backup file is not corrupt and the target metadata engine is empty before loading (duplicate keys can change affected-row counts).
  3. Check the database server error log for silently dropped or truncated statements and ensure the table schema matches the dump version.
  4. If a specific engine consistently misreports counts, upgrade JuiceFS and file an issue with the engine type and driver version.

Example fix

// before
n, err := s.Insert(beans[:bs])
if err == nil && int(n) != bs {
    err = fmt.Errorf("only %d records inserted", n)
}
// after (operator-side: load into a clean, empty database)
# ensure target tables are empty first
juicefs dump sqlite3://old.db out.json
rm -f new.db && juicefs format sqlite3://new.db vol
juicefs load sqlite3://new.db out.json
Defensive patterns

Strategy: validation

Validate before calling

rows, _ := targetDB.Query("SELECT COUNT(*) FROM jfs_...") // confirm target tables are empty before load

Try / catch

if err := juicefsLoad(metaURL, dumpFile); err != nil { log.Fatalf("load failed (partial write possible, re-load into clean DB): %v", err) }

Prevention

When it happens

Trigger: Calling `juicefs load` (meta.Load/Write fallback path) where `s.Insert(beans[:bs])` returns n < bs, e.g. the database silently skipped rows due to a driver quirk, row-count truncation, or a replaced row counting as fewer affected rows.

Common situations: Restoring a large dump into MySQL/PostgreSQL/SQLite where the driver reports affected-row counts differently (e.g. CLIENT_FOUND_ROWS off, upserts counting as 2), or a storage-side constraint swallowed part of the batch.

Related errors


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