wavetermdev/waveterm · error

no active pty

Error message

no active pty

What it means

setTermSize_withlock resizes the job's PTY, but requires jm.cmdPty to be set. If the PTY handle is nil, no pty was started (or it was never assigned), and resizing is impossible, so this error is returned.

Source

Thrown at pkg/jobmanager/jobcmd.go:157

	defer jm.lock.Unlock()
	if !jm.processExited {
		return false, nil
	}
	exitData := &wshrpc.CommandJobCmdExitedData{
		JobId:      WshCmdJobManager.JobId,
		ExitCode:   jm.exitCode,
		ExitSignal: jm.exitSignal,
		ExitTs:     jm.exitTs,
	}
	if jm.exitErr != nil {
		exitData.ExitErr = jm.exitErr.Error()
	}
	return true, exitData
}

func (jm *JobCmd) setTermSize_withlock(termSize waveobj.TermSize) error {
	if jm.cmdPty == nil {
		return fmt.Errorf("no active pty")
	}
	if jm.termSize.Rows == termSize.Rows && jm.termSize.Cols == termSize.Cols {
		return nil
	}
	err := pty.Setsize(jm.cmdPty, &pty.Winsize{
		Rows: uint16(termSize.Rows),
		Cols: uint16(termSize.Cols),
	})
	if err != nil {
		return fmt.Errorf("error setting terminal size: %w", err)
	}
	jm.termSize = termSize
	return nil
}

func (jm *JobCmd) SetTermSize(termSize waveobj.TermSize) error {
	jm.lock.Lock()
	defer jm.lock.Unlock()

View on GitHub (pinned to a4447c1563)

Solutions

  1. Ensure StartJob succeeded before issuing SetTermSize/input.
  2. Check the job's running state before sending resize RPCs.
  3. Handle the error gracefully in the client (ignore resize for non-running jobs).
  4. Restart the job if the PTY was lost.

Example fix

// before
err := jobCmd.SetTermSize(size)
// after
if !jobMgr.IsRunning() {
    return nil // nothing to resize
}
err := jobCmd.SetTermSize(size)
Defensive patterns

Strategy: validation

Validate before calling

if !jobRunning { // confirm StartJob succeeded before resizing
    return errors.New("skip resize: no job running")
}

Type guard

func canResize(jm *jobmanager.JobCmd) bool {
    exited, _ := jm.GetExitInfo()
    return !exited
}

Try / catch

err := jobCmd.SetTermSize(termSize)
if err != nil {
    if err.Error() == "no active pty" {
        return nil // job not started or already torn down; ignore resize
    }
    return err
}

Prevention

When it happens

Trigger: SetTermSize or HandleInput (which resizes on first input) invoked on a JobCmd whose pty.StartWithSize never ran or failed — e.g. resizing a block whose job failed to launch, or before StartJob completes.

Common situations: Client sends a resize RPC for a block whose job crashed at startup; race where the UI resizes immediately after job creation but before the process starts.

Related errors


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