{"record":{"id":"ed62d4a9ff80082f","repo":"juicedata/juicefs","slug":"d-records-not-inserted-v","errorCode":null,"errorMessage":"%d records not inserted: %+v","messagePattern":"(.+?) records not inserted: %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/sql.go","lineNumber":1030,"sourceCode":"\t\t\t\tm.genLog(Background(), s, time.Now().UnixNano(), \"SET(%s,%d)\", logEncode2(name), value)\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t})\n\n\treturn changed, err\n}\n\nfunc mustInsert(s *xorm.Session, beans ...interface{}) error {\n\tfor start, end, size := 0, 0, len(beans); end < size; start = end {\n\t\tend = start + 200\n\t\tif end > size {\n\t\t\tend = size\n\t\t}\n\t\tif n, err := s.Insert(beans[start:end]...); err != nil {\n\t\t\treturn err\n\t\t} else if d := end - start - int(n); d > 0 {\n\t\t\treturn fmt.Errorf(\"%d records not inserted: %+v\", d, beans[start:end])\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (m *dbMeta) batchUpdateChunkRefs(s *xorm.Session, chunkRefDeltas map[uint64]int) error {\n\tif len(chunkRefDeltas) == 0 {\n\t\treturn nil\n\t}\n\tchunkIds := make([]uint64, 0, len(chunkRefDeltas))\n\tfor id, delta := range chunkRefDeltas {\n\t\tif delta != 0 {\n\t\t\tchunkIds = append(chunkIds, id)\n\t\t}\n\t}\n\tif len(chunkIds) == 0 {\n\t\treturn nil\n\t}","sourceCodeStart":1012,"sourceCodeEnd":1048,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/sql.go#L1012-L1048","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the listed beans (%+v) and check for duplicate primary keys or NULL key fields in the batch.","Retry the operation; if it persists, test with a stock database driver version.","File a bug with the driver name/version if a supported driver reliably short-inserts."],"exampleFix":"// before: n < len(beans) with no error, mustInsert aborts the txn\n// after: deduplicate beans before batch insert\nseen := make(map[uint64]bool)\nuniq := beans[:0]\nfor _, b := range beans { if !seen[key(b)] { seen[key(b)] = true; uniq = append(uniq, b) } }\nerr := mustInsert(s, uniq...)","handlingStrategy":"validation","validationCode":"// ensure batch inserts have unique, fully-populated primary keys\nkeys := make(map[interface{}]bool)\nfor _, b := range beans {\n    k := primaryKey(b)\n    if k == nil || keys[k] { return fmt.Errorf(\"bad batch: dup/nil key %v\", k) }\n    keys[k] = true\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"records not inserted\") {\n    logger.Errorf(\"short insert detected, aborting txn; driver=%s beans=%v\", driverName, err)\n    return err // txn rolls back; retry with deduplicated batch\n}","preventionTips":["Use stock, supported database drivers; avoid patched drivers that misreport RowsAffected.","Deduplicate bean batches on primary key before mustInsert.","Keep xorm and driver versions aligned with upstream JuiceFS go.mod."],"tags":["database","insert","invariant","go"],"backgroundTag":"database-write-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}