wavetermdev/waveterm · error

job is not connected (status: %s)

Error message

job is not connected (status: %s)

What it means

CheckJobConnected performs a two-step check: the raw connection must be up, and GetJobConnStatus(jobId) must return JobConnStatus_Connected. This error means the in-memory job-level connection status disagrees with the transport state — the conn is up but the job itself hasn't (or no longer) registered as connected.

Source

Thrown at pkg/jobcontroller/jobcontroller.go:597

}

func CheckJobConnected(ctx context.Context, jobId string) (*waveobj.Job, error) {
	job, err := wstore.DBMustGet[*waveobj.Job](ctx, jobId)
	if err != nil {
		return nil, fmt.Errorf("failed to get job: %w", err)
	}

	isConnected, err := conncontroller.IsConnected(job.Connection)
	if err != nil {
		return nil, fmt.Errorf("error checking connection status: %w", err)
	}
	if !isConnected {
		return nil, fmt.Errorf("connection %q is not connected", job.Connection)
	}

	jobConnStatus := GetJobConnStatus(jobId)
	if jobConnStatus != JobConnStatus_Connected {
		return nil, fmt.Errorf("job is not connected (status: %s)", jobConnStatus)
	}

	return job, nil
}

type StartJobParams struct {
	ConnName string
	JobKind  string
	Cmd      string
	Args     []string
	Env      map[string]string
	TermSize *waveobj.TermSize
	BlockId  string
}

func StartJob(ctx context.Context, params StartJobParams) (string, error) {
	if params.ConnName == "" {
		return "", fmt.Errorf("connection name is required")

View on GitHub (pinned to a4447c1563)

Solutions

  1. Wait briefly and retry until job status becomes Connected
  2. Restart the job if its status is terminally degraded
  3. Check logs for the remote job's exit reason
  4. Serialize SendInput behind a connected-state gate instead of calling directly

Example fix

// before
_, err := jobcontroller.CheckJobConnected(ctx, jobId)
if err != nil {
	return err
}
// after
err := waitForCondition(func() bool {
	_, err := jobcontroller.CheckJobConnected(ctx, jobId)
	return err == nil
}, 5*time.Second)
if err != nil {
	return fmt.Errorf("job %s never became connected: %w", jobId, err)
}
Defensive patterns

Strategy: retry

Validate before calling

if jobcontroller.GetJobConnStatus(jobId) != jobcontroller.JobConnStatus_Connected {
	return fmt.Errorf("job %s not ready for input", jobId)
}

Type guard

func isJobStatusMismatchErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "job is not connected (status:")
}

Try / catch

_, err := jobcontroller.CheckJobConnected(ctx, jobId)
if isJobStatusMismatchErr(err) {
	time.Sleep(250 * time.Millisecond)
	_, err = jobcontroller.CheckJobConnected(ctx, jobId)
}
if err != nil { return err }

Prevention

When it happens

Trigger: Calling CheckJobConnected when GetJobConnStatus returns any status other than Connected — job starting up, job torn down on the remote side, or stale job-status map entry after a reconnect.

Common situations: Sending input immediately after StartJob before the job's connection handshake finishes; remote shell exited and the status degraded; reconnect race where conn is up but the job is not yet reattached.

Related errors


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