juicedata/juicefs · error

%d records not inserted: %+v

Error message

%d records not inserted: %+v

What it means

Thrown by the mustInsert helper when xorm's s.Insert reports success but the affected-row count is fewer than the number of beans in the batch (up to 200 per batch). This is an internal invariant: in normal SQL semantics a successful multi-row INSERT either affects all rows or errors, so a short insert signals rows silently skipped (e.g. driver quirks or ON-CONFLICT behaviors).

Source

Thrown at pkg/meta/sql.go:1030

				m.genLog(Background(), s, time.Now().UnixNano(), "SET(%s,%d)", logEncode2(name), value)
			}
			return err
		}
	})

	return changed, err
}

func mustInsert(s *xorm.Session, beans ...interface{}) error {
	for start, end, size := 0, 0, len(beans); end < size; start = end {
		end = start + 200
		if end > size {
			end = size
		}
		if n, err := s.Insert(beans[start:end]...); err != nil {
			return err
		} else if d := end - start - int(n); d > 0 {
			return fmt.Errorf("%d records not inserted: %+v", d, beans[start:end])
		}
	}
	return nil
}

func (m *dbMeta) batchUpdateChunkRefs(s *xorm.Session, chunkRefDeltas map[uint64]int) error {
	if len(chunkRefDeltas) == 0 {
		return nil
	}
	chunkIds := make([]uint64, 0, len(chunkRefDeltas))
	for id, delta := range chunkRefDeltas {
		if delta != 0 {
			chunkIds = append(chunkIds, id)
		}
	}
	if len(chunkIds) == 0 {
		return nil
	}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Inspect the listed beans (%+v) and check for duplicate primary keys or NULL key fields in the batch.
  2. Retry the operation; if it persists, test with a stock database driver version.
  3. File a bug with the driver name/version if a supported driver reliably short-inserts.

Example fix

// before: n < len(beans) with no error, mustInsert aborts the txn
// after: deduplicate beans before batch insert
seen := make(map[uint64]bool)
uniq := beans[:0]
for _, b := range beans { if !seen[key(b)] { seen[key(b)] = true; uniq = append(uniq, b) } }
err := mustInsert(s, uniq...)
Defensive patterns

Strategy: validation

Validate before calling

// ensure batch inserts have unique, fully-populated primary keys
keys := make(map[interface{}]bool)
for _, b := range beans {
    k := primaryKey(b)
    if k == nil || keys[k] { return fmt.Errorf("bad batch: dup/nil key %v", k) }
    keys[k] = true
}

Try / catch

if err != nil && strings.Contains(err.Error(), "records not inserted") {
    logger.Errorf("short insert detected, aborting txn; driver=%s beans=%v", driverName, err)
    return err // txn rolls back; retry with deduplicated batch
}

Prevention

When it happens

Trigger: Any call site using mustInsert (session creation, chunk insertion, trash edge insertion, counter insert) where the driver returns a rowcount < len(beans) without an error — practically a driver/ORM anomaly or a batch containing duplicate primary keys with certain dialect configurations.

Common situations: Custom/patched SQL drivers that misreport affected rows; bulk inserts (e.g. during `juicefs fsck` re-linking or big trash scans) where a driver bug drops rows; extremely unusual on stock MySQL/PostgreSQL/SQLite drivers.

Related errors


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