dagger/dagger · error

starting client terminal session: %w

Error message

starting client terminal session: %w

What it means

Returned by TerminalProxy.Session when opening the outbound gRPC client stream to the upstream terminal service fails. The proxy accepts an incoming Session stream, then dials a client Session on the target engine; if that Dial/Session call errors (connection refused, unavailable, auth), the proxy returns this wrapped error.

Source

Thrown at engine/session/terminal/terminal.go:200

}

func NewTerminalProxy(client TerminalClient) TerminalProxy {
	return TerminalProxy{
		client: client,
	}
}

func (p TerminalProxy) Register(srv *grpc.Server) {
	RegisterTerminalServer(srv, p)
}

func (p TerminalProxy) Session(stream Terminal_SessionServer) error {
	ctx, cancel := context.WithCancelCause(stream.Context())
	defer cancel(errors.New("proxy stream closed"))

	clientStream, err := p.client.Session(grpcutil.IncomingToOutgoingContext(ctx))
	if err != nil {
		return fmt.Errorf("starting client terminal session: %w", err)
	}
	return grpcutil.ProxyStream[anypb.Any](ctx, clientStream, stream)
}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Check connectivity to the target engine (dagger core dump / engine status) and retry
  2. Ensure the engine session is fully started before attaching a terminal
  3. Inspect proxy stream context cancellation — a cancelled incoming stream aborts the client dial
  4. Verify TLS/metadata (grpcutil.IncomingToOutgoingContext) forwards required auth headers

Example fix

// before
clientStream, err := p.client.Session(grpcutil.IncomingToOutgoingContext(ctx))
if err != nil { return fmt.Errorf("starting client terminal session: %w", err) }
// after
clientStream, err := p.client.Session(grpcutil.IncomingToOutgoingContext(ctx))
if err != nil {
	if status.Code(err) == codes.Unavailable { /* retry with backoff */ }
	return fmt.Errorf("starting client terminal session: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

# shell: confirm the engine is reachable before opening a terminal session
dagger query --help >/dev/null 2>&1 || { echo 'engine unreachable'; exit 1; }

Try / catch

err := openTerminalSession(ctx)
if err != nil {
	if status.Code(errors.Unwrap(err)) == codes.Unavailable {
		// backoff and reconnect to the engine, then retry
		return retryWithBackoff(openTerminalSession, ctx)
	}
	return err
}

Prevention

When it happens

Trigger: A TerminalProxy is registered (e.g. engine-to-engine or session-to-CLI proxying) and p.client.Session(ctx) fails at stream creation — target engine unreachable, gRPC server not yet serving, context already cancelled, or TLS/auth rejection.

Common situations: dagger terminal against a remote/cloud engine where the engine connection dropped; nested terminal proxying (dagger-in-dagger) where the inner engine hasn't started; network partitions or VPN drops during session attach.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/888ff57af4b38b2c. Report an issue: GitHub.