juicedata/juicefs · error
update table node: %s
Error message
update table node: %s
What it means
During legacy schema upgrade in doNewSession, after syncing added tables, JuiceFS syncs the node table (needed to add the primary key). A syncTable(new(node)) failure is wrapped as 'update table node: %s' and aborts the mount.
Source
Thrown at pkg/meta/sql.go:772
s := setting{Name: "format"}
ok, err := ses.Get(&s)
if err == nil && ok {
data = []byte(s.Value)
}
return err
})
return
}
func (m *dbMeta) doNewSession(sinfo []byte, update bool) error {
// add new table
err := m.syncTable(new(session2), new(delslices), new(dirStats), new(detachedNode), new(dirQuota), new(userGroupQuota), new(acl), new(delegationToken), new(changeLog))
if err != nil {
return fmt.Errorf("update table session2, delslices, dirstats, detachedNode, dirQuota, userGroupQuota, acl, changeLog: %s", err)
}
// add node table
if err = m.syncTable(new(node)); err != nil {
return fmt.Errorf("update table node: %s", err)
}
// add primary key
if err = m.syncTable(new(edge), new(chunk), new(xattr), new(sustained)); err != nil {
return fmt.Errorf("update table edge, chunk, xattr, sustained: %s", err)
}
// update the owner from uint64 to int64
if err = m.syncTable(new(flock), new(plock)); err != nil {
return fmt.Errorf("update table flock, plock: %s", err)
}
for {
beans := session2{Sid: m.sid, Expire: m.expireTime(), Info: sinfo}
if update {
return m.txn(func(s *xorm.Session) error {
_, err = s.Cols("expire", "info").Update(&beans, &session2{Sid: beans.Sid})
if err == nil {
m.genLog(Background(), s, time.Now().UnixNano(), "NEWSESSION(%d,%d,%s)", m.sid, beans.Expire, logEncode(sinfo))
}View on GitHub (pinned to c9a67b23e8)
Solutions
- Check for duplicate Inode rows in the node table and deduplicate before the upgrade (juicefs fsck can help)
- Grant ALTER privilege to the metadata user
- Kill long-running transactions holding locks on the node table and retry the mount
- Back up the metadata before the schema upgrade
Example fix
-- before ALTER TABLE jfs_node ADD PRIMARY KEY (inode); -- fails on duplicates -- after -- dedupe first, e.g. keep min(rowid) per inode, then re-run mount so syncTable adds the primary key
Defensive patterns
Strategy: validation
Validate before calling
-- Check for duplicate inodes blocking the primary key before upgrading SELECT inode, COUNT(*) c FROM node GROUP BY inode HAVING c > 1;
Try / catch
if err := mount(sqlURL); err != nil {
if strings.Contains(err.Error(), "update table node") {
log.Fatalf("dedupe node.inode rows and retry: %v", err)
}
} Prevention
- Run juicefs fsck before major upgrades
- Grant ALTER privileges
- Avoid lock-heavy concurrent transactions during upgrade
When it happens
Trigger: Mounting an old-format volume when altering the node table fails — e.g. duplicate rows preventing primary key creation, insufficient ALTER privilege, or lock timeout on a large node table.
Common situations: Upgrading a volume with duplicate inode rows in node (prevents adding primary key); RDS account without ALTER; long-running transaction holding metadata locks on node.
Related errors
- update table edge, chunk, xattr, sustained: %s
- update table session2, delslices, dirstats, detachedNode, di
- update table flock, plock: %s
- create table delegationToken: %s
- create table changeLog: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/f06106015135e3bf.
Report an issue: GitHub.