wavetermdev/waveterm · error

route did not establish after successful reconnection: %w

Error message

route did not establish after successful reconnection: %w

What it means

This error is returned when the remote reconnect RPC reported success but the local wshutil.DefaultRouter never saw the job's route register within the 2-second window (jobcontroller.go:1155). WaitForRegister(waitCtx, routeId) times out or fails, meaning the job manager never finished establishing its message route back to this server despite the reconnect command nominally succeeding.

Source

Thrown at pkg/jobcontroller/jobcontroller.go:1155

				Props: telemetrydata.TEventProps{
					JobDoneReason: JobDoneReason_Gone,
					JobKind:       job.JobKind,
				},
			})
			writeJobTerminationMessage(ctx, jobId, updatedJob, "[session gone]")
			return fmt.Errorf("job manager has exited: %s", rtnData.Error)
		}
		return fmt.Errorf("failed to reconnect to job manager: %s", rtnData.Error)
	}

	log.Printf("[job:%s] RemoteReconnectToJobManagerCommand succeeded, waiting for route", jobId)

	routeId := wshutil.MakeJobRouteId(jobId)
	waitCtx, cancelFn := context.WithTimeout(ctx, 2*time.Second)
	defer cancelFn()
	err = wshutil.DefaultRouter.WaitForRegister(waitCtx, routeId)
	if err != nil {
		return fmt.Errorf("route did not establish after successful reconnection: %w", err)
	}
	SetJobConnStatus(jobId, JobConnStatus_Connected)
	sendBlockJobStatusEventByJob(ctx, job)

	telemetry.GoRecordTEventWrap(&telemetrydata.TEvent{
		Event: "job:reconnect",
		Props: telemetrydata.TEventProps{
			JobKind: job.JobKind,
		},
	})

	log.Printf("[job:%s] route established, restarting streaming", jobId)
	return restartStreaming(ctx, jobId, true, rtOpts)
}

func ReconnectJobsForConn(ctx context.Context, connName string) error {
	isConnected, err := conncontroller.IsConnected(connName)
	if err != nil {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Retry ReconnectJob — a second attempt often succeeds once the route settles.
  2. Increase tolerance by retrying with backoff rather than treating it as fatal immediately.
  3. Check that the websocket/connection stayed up during the 2s window (look for conn drops in logs).
  4. If persistent, verify the remote job manager process is actually alive on the host.

Example fix

// before
err := jobcontroller.ReconnectJob(ctx, jobId, nil) // may fail: route timeout
// after
var err error
for i := 0; i < 3; i++ {
    if err = jobcontroller.ReconnectJob(ctx, jobId, nil); err == nil {
        break
    }
    if !strings.Contains(err.Error(), "route did not establish") {
        break
    }
    time.Sleep(500 * time.Millisecond)
}
Defensive patterns

Strategy: retry

Validate before calling

// verify the conn/websocket stayed up before/after reconnect attempt

Try / catch

if err := jobcontroller.ReconnectJob(ctx, jobId, nil); err != nil && strings.Contains(err.Error(), "route did not establish") {
    // transient: retry after short delay
    time.Sleep(500 * time.Millisecond)
    err = jobcontroller.ReconnectJob(ctx, jobId, nil)
}

Prevention

When it happens

Trigger: wshutil.DefaultRouter.WaitForRegister(ctx, wshutil.MakeJobRouteId(jobId)) returns error (context deadline exceeded after 2s) after a successful RemoteReconnectToJobManagerCommand — the remote accepted the reconnect but the job route never registered locally.

Common situations: 1) Slow remote/network where the job manager needs >2s to spin up and register its route. 2) The job manager died right after accepting the reconnect. 3) Message routing issues between the remote daemon and main server (websocket hiccup).

Related errors


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