juicedata/juicefs · error

corrupted session info; json error: %s

Error message

corrupted session info; json error: %s

What it means

Thrown by dbMeta.getSession when the session's serialized `info` JSON column cannot be unmarshalled into a Session. The info column holds client metadata (hostname, IPs, process, mountpoint) written as JSON at session creation; if it is corrupt or not valid JSON matching the Session schema, GetSession/FindSession fails for that session.

Source

Thrown at pkg/meta/sql.go:839

	var s Session
	var info []byte
	switch row := row.(type) {
	case *session2:
		s.Sid = row.Sid
		s.Expire = time.Unix(row.Expire, 0)
		info = row.Info
	case *session:
		s.Sid = row.Sid
		s.Expire = time.Unix(row.Heartbeat, 0).Add(time.Minute * 5)
		info = row.Info
		if info == nil { // legacy client has no info
			info = []byte("{}")
		}
	default:
		return nil, fmt.Errorf("invalid type: %T", row)
	}
	if err := json.Unmarshal(info, &s); err != nil {
		return nil, fmt.Errorf("corrupted session info; json error: %s", err)
	}
	if detail {
		var (
			srows []sustained
			frows []flock
			prows []plock
		)
		err := m.roTxn(Background(), func(ses *xorm.Session) error {
			if err := ses.Find(&srows, &sustained{Sid: s.Sid}); err != nil {
				return fmt.Errorf("find sustained %d: %s", s.Sid, err)
			}
			s.Sustained = make([]Ino, 0, len(srows))
			for _, srow := range srows {
				s.Sustained = append(s.Sustained, srow.Inode)
			}

			if err := ses.Find(&frows, &flock{Sid: s.Sid}); err != nil {
				return fmt.Errorf("find flock %d: %s", s.Sid, err)

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Check the offending row: `SELECT sid, info FROM jfs_session2 WHERE sid=<id>` and fix or delete it if it is stale.
  2. If the session is dead, run `juicefs gc --delete` or wait for stale-session cleanup (doCleanStaleSession) to remove the row.
  3. If rows were corrupted by a restore, re-run session info writers by remounting clients.
  4. For SQLite, run integrity_check; for MySQL, check table corruption and repair.

Example fix

// before: SELECT info shows truncated JSON: '{"ip":["10.0.0', unmarshal fails
// after: remove stale/corrupt row, then re-query
DELETE FROM jfs_session2 WHERE sid = 42;
juicefs status sqlite3://test.db
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate a session's info JSON before inspecting status output
var probe map[string]interface{}
if err := json.Unmarshal(info, &probe); err != nil {
    log.Printf("session info corrupt, treat session as stale: %v", err)
}

Type guard

func validSessionInfo(info []byte) bool {
    var s map[string]interface{}
    return json.Unmarshal(info, &s) == nil
}

Try / catch

s, err := m.GetSession(sid, false)
if err != nil && strings.Contains(err.Error(), "corrupted session info") {
    logger.Warnf("skipping corrupt session %d: %v", sid, err) // treat as stale, allow cleanup
    return nil
}

Prevention

When it happens

Trigger: `juicefs status <meta-url>` or `juicefs info` listing sessions where a row's info column was truncated, manually edited, written by a client with a legacy nil-info column containing garbage, or corrupted by a DB incident/partial backup restore.

Common situations: Restoring a database backup mid-write; manual DB surgery on the session table; very old clients (pre-info schema) combined with corrupted rows; disk-level corruption on self-hosted MySQL/SQLite.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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