livekit/livekit · error

could not update egress info

Error message

could not update egress info

What it means

UpdateEgress writes updated EgressInfo back to Redis — through a pipeline (with room-set bookkeeping) in one branch, or a plain HSet otherwise; any resulting error is wrapped as 'could not update egress info'. Status updates for running egress are lost if Redis is unhealthy.

Source

Thrown at pkg/service/redisstore.go:465

}

func (s *RedisStore) UpdateEgress(_ context.Context, info *livekit.EgressInfo) error {
	data, err := proto.Marshal(info)
	if err != nil {
		return err
	}

	if info.EndedAt != 0 {
		pp := s.rc.Pipeline()
		pp.HSet(s.ctx, EgressKey, info.EgressId, data)
		pp.HSet(s.ctx, EndedEgressKey, info.EgressId, egressEndedValue(info.RoomName, info.EndedAt))
		_, err = pp.Exec(s.ctx)
	} else {
		err = s.rc.HSet(s.ctx, EgressKey, info.EgressId, data).Err()
	}

	if err != nil {
		return errors.Wrap(err, "could not update egress info")
	}

	return nil
}

// Deletes egress info 24h after the egress has ended
func (s *RedisStore) egressWorker() {
	ticker := time.NewTicker(time.Minute * 30)
	defer ticker.Stop()

	for {
		select {
		case <-s.done:
			return
		case <-ticker.C:
			err := s.CleanEndedEgress()
			if err != nil {
				logger.Errorw("could not clean egress info", err)

View on GitHub (pinned to ee45c3f0b1)

Solutions

  1. Confirm the Redis endpoint is a writable master (INFO replication) and fix routing if pointing at a replica.
  2. Check Redis and livekit logs for the underlying cause (READONLY/MOVED/timeout).
  3. Ensure egress nodes and Redis share stable connectivity; add retries with backoff around updates.
  4. In cluster setups, use a cluster-aware client so key-slot moves are followed.
  5. Monitor maxmemory; large EgressInfo payloads can push Redis over the limit.
Defensive patterns

Strategy: retry

Validate before calling

if err := s.rc.Ping(ctx).Err(); err != nil {
    return fmt.Errorf("redis unavailable, egress update will fail: %w", err)
}

Try / catch

if err := store.UpdateEgress(ctx, info, mutate); err != nil {
    if strings.Contains(err.Error(), "could not update egress info") {
        // retry status update; egress status converges on success
        backoff.Retry(func() error { return store.UpdateEgress(ctx, info, mutate) }, policy)
    }
}

Prevention

When it happens

Trigger: Either pp.Exec (pipeline branch) or HSet(EgressKey, egressId, data).Err() (single-key branch) returns a Redis error: connection drop, READONLY, timeout, cluster redirect, or OOM.

Common situations: Status updates failing during a Redis failover; long-running egress sessions spanning Redis restarts; writing through a replica; transient network partitions.

Related errors


AI-assisted analysis of livekit/livekit@ee45c3f0b1 (2026-09-02). Data as JSON: /api/errors/d6a6d275d9475118. Report an issue: GitHub.