juicedata/juicefs · error

failed command %d %+v: %w

Error message

failed command %d %+v: %w

What it means

execPipe runs a batch of read commands (used by loadNodes, loadEdges, loadChunks, loadSustained, loadXattrs) and, when pipe.Exec fails, returns the first individual command that errored along with its index and string form. This pinpoints which specific Redis command in the load pipeline failed during metadata load/restore.

Source

Thrown at pkg/meta/redis_bak.go:730

	case segTypeStat:
		return m.loadDirStats(ctx, val)
	case segTypeParent:
		return m.loadParents(ctx, val)
	default:
		logger.Warnf("skip segment type %d", typ)
		return nil
	}
}

func execPipe(ctx context.Context, pipe redis.Pipeliner) error {
	if pipe.Len() == 0 {
		return nil
	}
	cmds, err := pipe.Exec(ctx)
	if err != nil {
		for i, cmd := range cmds {
			if cmd.Err() != nil {
				return fmt.Errorf("failed command %d %+v: %w", i, cmd, cmd.Err())
			}
		}
	}
	return err
}

func (m *redisMeta) loadFormat(ctx Context, msg proto.Message) error {
	return m.rdb.Set(ctx, m.setting(), msg.(*pb.Format).Data, 0).Err()
}

func (m *redisMeta) loadCounters(ctx Context, msg proto.Message) error {
	cs := make(map[string]interface{})

	for _, c := range msg.(*pb.Batch).Counters {
		if c.Key == "nextInode" || c.Key == "nextChunk" {
			cs[m.counterKey(c.Key)] = c.Value - 1
		} else {
			cs[m.counterKey(c.Key)] = c.Value

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Ensure the target database is empty before load (prepareLoad enforces this — run `juicefs load` against a flushed/new DB).
  2. Read the wrapped cmd.Err(): fix WRONGTYPE conflicts by removing conflicting keys, or raise maxmemory.
  3. When loading into a cluster, use the same cluster topology or hash tags as the source, or load via a standalone Redis then migrate.
  4. Check Redis server logs for OOM or connection issues during the load.

Example fix

// before
if err := m.execPipe(ctx, txp, func(pipe redis.Pipeliner) error { ... }); err != nil {
    return err
}
// after
if err := m.execPipe(ctx, txp, func(pipe redis.Pipeliner) error { ... }); err != nil {
    log.Fatalf("metadata load failed, check target DB is empty: %v", err)
}
Defensive patterns

Strategy: validation

Validate before calling

n, _ := rdb.DBSize(ctx).Result()
if n != 0 { return fmt.Errorf("target DB not empty (%d keys); load would conflict", n) }

Try / catch

if err := load(ctx, meta, f); err != nil {
    if strings.Contains(err.Error(), "WRONGTYPE") {
        log.Fatalf("target DB holds conflicting keys; flush it before load: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Restoring or loading metadata (juicefs load, warmup paths) when one queued command fails: WRONGTYPE on an existing key, OOM at the server, MOVED errors on a cluster whose keys were not migrated, or connection loss mid-exec.

Common situations: Loading a dump into a non-empty Redis database holding conflicting keys of different types; loading a single-node dump into a ClusterClient; Redis maxmemory reached during bulk load.

Related errors


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