wavetermdev/waveterm · error

failed to set rwnd size

Error message

failed to set rwnd size: %w

What it means

After a successful attach, StartStream applies the receiver-window size negotiated in pendingStreamMeta via StreamManager.SetRwndSize. This error wraps any failure from that call. It indicates the stream is attached but flow-control configuration could not be applied, so the stream is left partially initialized.

Solutions

  1. Log jm.pendingStreamMeta.RWnd and the wrapped error to see whether the negotiated value is sane
  2. Validate RWnd is > 0 (and within protocol bounds) before calling StartStream; re-run PrepareConnect if not
  3. Re-do the PrepareConnect/StartStream cycle to renegotiate a fresh window size
  4. Check StreamManager initialization order so SetRwndSize runs on a ready stream

Example fix

// before
jm.StartStream() // trusts pendingStreamMeta.RWnd
// after
if jm.pendingStreamMeta == nil || jm.pendingStreamMeta.RWnd == 0 {
    return fmt.Errorf("invalid rwnd negotiated, re-run PrepareConnect")
}
if err := jm.StartStream(); err != nil {
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

if jm.pendingStreamMeta == nil || jm.pendingStreamMeta.RWnd == 0 {
    return fmt.Errorf("invalid stream metadata/rwnd, re-run PrepareConnect")
}

Type guard

func validPendingStream(jm *JobManager) bool {
    return jm.pendingStreamMeta != nil && jm.pendingStreamMeta.RWnd > 0
}

Try / catch

if err := jm.StartStream(); err != nil {
    if strings.HasPrefix(err.Error(), "failed to set rwnd size") {
        log.Printf("rwnd error: %v", errors.Unwrap(err))
        // renegotiate and retry
        if perr := jm.PrepareConnect(); perr == nil {
            err = jm.StartStream()
        }
    }
    return err
}

Prevention

When it happens

Trigger: SetRwndSize returns an error — typically an invalid, zero, or out-of-range RWnd value in pendingStreamMeta, or the StreamManager rejecting the resize for an attached/invalid stream state.

Common situations: Peer negotiated a bad RWnd value during PrepareConnect; integer overflow/widening issue in int(jm.pendingStreamMeta.RWnd); StreamManager not fully initialized before StartStream; version skew where window-size semantics changed.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/ed5978ec3d043dc9. Report an issue: GitHub.

Appendix: source

Thrown at pkg/jobmanager/jobmanager.go:371

func (jm *JobManager) StartStream(msc *MainServerConn) error {
	jm.lock.Lock()
	defer jm.lock.Unlock()

	if jm.Cmd == nil {
		return fmt.Errorf("job not started")
	}
	if jm.pendingStreamMeta == nil {
		return fmt.Errorf("no pending stream (call PrepareConnect first)")
	}

	err := msc.WshRpc.StreamBroker.AttachStreamWriter(jm.pendingStreamMeta, jm.StreamManager)
	if err != nil {
		return fmt.Errorf("failed to attach stream writer: %w", err)
	}

	err = jm.StreamManager.SetRwndSize(int(jm.pendingStreamMeta.RWnd))
	if err != nil {
		return fmt.Errorf("failed to set rwnd size: %w", err)
	}

	log.Printf("StartStream: streamid=%s rwnd=%d streaming started\n", jm.pendingStreamMeta.Id, jm.pendingStreamMeta.RWnd)
	jm.pendingStreamMeta = nil
	return nil
}

func MakeJobDomainSocket(clientId string, jobId string) error {
	socketDir := filepath.Join("/tmp", fmt.Sprintf("waveterm-%d", os.Getuid()))
	err := os.MkdirAll(socketDir, 0700)
	if err != nil {
		return fmt.Errorf("failed to create socket directory: %w", err)
	}

	socketPath := wavebase.GetRemoteJobSocketPath(jobId)

	os.Remove(socketPath)

View on GitHub (pinned to a4447c1563)