{"record":{"id":"d703d632a9e6c47c","repo":"juicedata/juicefs","slug":"not-inserted-or-updated","errorCode":null,"errorMessage":"not inserted or updated","messagePattern":"not inserted or updated","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/object/sql.go","lineNumber":104,"sourceCode":"\t}\n\tvar n int64\n\tnow := time.Now()\n\tb := blob{Key: []byte(key), Data: d, Size: int64(len(d)), Modified: now}\n\tif name := s.db.DriverName(); name == \"postgres\" || name == \"pgx\" {\n\t\tvar r sql.Result\n\t\tr, err = s.db.Exec(\"INSERT INTO jfs_blob(key, size,modified, data) VALUES(?, ?, ?,? ) \"+\n\t\t\t\"ON CONFLICT (key) DO UPDATE SET size=?,data=?\", []byte(key), b.Size, now, d, b.Size, d)\n\t\tif err == nil {\n\t\t\tn, err = r.RowsAffected()\n\t\t}\n\t} else {\n\t\tn, err = s.db.Insert(&b)\n\t\tif err != nil || n == 0 {\n\t\t\tn, err = s.db.Update(&b, &blob{Key: []byte(key)})\n\t\t}\n\t}\n\tif err == nil && n == 0 {\n\t\terr = errors.New(\"not inserted or updated\")\n\t}\n\treturn err\n}\n\nfunc (s *sqlStore) Head(ctx context.Context, key string) (Object, error) {\n\tvar b = blob{Key: []byte(key)}\n\tok, err := s.db.Cols(\"key\", \"modified\", \"size\").Get(&b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !ok {\n\t\treturn nil, os.ErrNotExist\n\t}\n\treturn &obj{\n\t\tkey,\n\t\tb.Size,\n\t\tb.Modified,\n\t\tstrings.HasSuffix(key, \"/\"),","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/object/sql.go#L86-L122","documentation":"sqlStore.Put reports \"not inserted or updated\" when both the INSERT and the fallback UPDATE affected zero rows (n == 0) without returning a driver error. The blob was not persisted, so the write is treated as failed.","triggerScenarios":"Insert fails or inserts 0 rows, the subsequent Update by primary key matches no existing row (key absent and insert silently no-op), or a driver quirk reports 0 affected rows on successful upserts.","commonSituations":"MySQL with default CLIENT_FOUND_ROWS off where an UPDATE with identical data reports 0 affected rows; SQLite/Postgres schema mismatches; races where another client deleted the row between insert and update.","solutions":["Retry the Put; transient row-count quirks often succeed on retry","Check the table schema (key column, primary key) matches what juicefs format created","Upgrade the Go SQL driver / ensure it reports affected rows correctly (e.g. enable clientFoundRows for MySQL)","Enable engine debug logging to capture the underlying insert/update errors"],"exampleFix":"// before\nn, err = s.db.Insert(&b)\nif err != nil || n == 0 {\n\tn, err = s.db.Update(&b, &blob{Key: []byte(key)})\n}\n// after\nn, err = s.db.Insert(&b)\nif err != nil || n == 0 {\n\tn, err = s.db.Update(&b, &blob{Key: []byte(key)})\n\tif n == 0 && err == nil {\n\t\tlogger.Warnf(\"put %s: 0 rows affected, retrying\", key)\n\t}\n}","handlingStrategy":"retry","validationCode":"// verify schema before writes\nrows, _ := db.Query(\"SHOW TABLES LIKE 'jfs_blob'\")\nif !rows.Next() { /* volume not formatted against this DB */ }","typeGuard":null,"tryCatchPattern":"err := store.Put(ctx, key, r)\nif err != nil && err.Error() == \"not inserted or updated\" {\n\ttime.Sleep(100*time.Millisecond)\n\terr = store.Put(ctx, key, r) // retry once\n}","preventionTips":["Keep the metadata schema aligned with the client version (re-run juicefs format/migrate as needed)","Enable MySQL clientFoundRows if identical-value updates report 0 rows","Watch engine logs for silent insert/update failures","Retry transient write anomalies"],"tags":["sql","object-storage","database-write"],"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-14T05:17:10.506Z"}