microsoft/aspire · critical

failed to authenticate to AppHost

Error message

failed to authenticate to AppHost: %w

What it means

After the socket connection succeeds, connect authenticates using the ASPIRE_REMOTE_APPHOST_TOKEN environment variable. If c.authenticate fails (wrong, missing, or expired token, or protocol mismatch during handshake), the connection is torn down and the cause is wrapped as "failed to authenticate to AppHost: %w".

Solutions

  1. Run the project through `aspire run` so ASPIRE_REMOTE_APPHOST_TOKEN is injected fresh and matches the current AppHost.
  2. Never hardcode or copy the token between sessions; it is per-run.
  3. Log the unwrapped error to distinguish bad token vs handshake/timeout failure.
  4. Restart both AppHost and project together so token and socket stay in sync.

Example fix

// before
authToken := os.Getenv("ASPIRE_REMOTE_APPHOST_TOKEN")
// after
authToken := os.Getenv("ASPIRE_REMOTE_APPHOST_TOKEN")
if authToken == "" {
    return fmt.Errorf("ASPIRE_REMOTE_APPHOST_TOKEN is not set; launch via `aspire run` instead of running directly")
}
Defensive patterns

Strategy: try-catch

Validate before calling

if os.Getenv("ASPIRE_REMOTE_APPHOST_TOKEN") == "" {
    log.Fatal("ASPIRE_REMOTE_APPHOST_TOKEN missing; launch via `aspire run`")
}

Try / catch

app, err := aspire.CreateBuilder(ctx)
if err != nil && strings.Contains(err.Error(), "failed to authenticate") {
    log.Fatal("stale or missing ASPIRE_REMOTE_APPHOST_TOKEN; restart via `aspire run`")
}

Prevention

When it happens

Trigger: ASPIRE_REMOTE_APPHOST_TOKEN is empty or doesn't match the token the AppHost expects; connecting to an AppHost from a different session/run whose token differs; authenticate handshake times out or the AppHost rejects the auth frame.

Common situations: Manually running the Go project with a stale token from a previous `aspire run` session; copying env vars between machines; AppHost regenerated its token after restart while the client kept the old value.

Understand the failure class

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/e7c1661fe4d9527d. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.CodeGeneration.Go/Resources/transport.go:644

		return fmt.Errorf("failed to connect to AppHost: %w", err)
	}

	authToken := os.Getenv("ASPIRE_REMOTE_APPHOST_TOKEN")
	if authToken == "" {
		cErr := rawConn.Close()
		c.mu.Unlock()
		return errors.Join(errors.New("ASPIRE_REMOTE_APPHOST_TOKEN environment variable is not set"), cErr)
	}

	conn := newConnection(rawConn, c, c.onConnectionClose)
	c.conn = conn
	c.mu.Unlock()

	conn.start()

	if err := c.authenticate(ctx, authToken); err != nil {
		c.disconnect()
		return fmt.Errorf("failed to authenticate to AppHost: %w", err)
	}

	return nil
}

// onDisconnect registers a callback to be invoked exactly once when the
// connection is closed.
func (c *client) onDisconnect(callback func()) {
	c.mu.Lock()
	c.disconnectCallbacks = append(c.disconnectCallbacks, callback)
	c.mu.Unlock()
}

// invokeCapability invokes a capability on the server. The supplied context
// drives both server-side cancellation (if a CancellationToken is registered
// in args) and local short-circuit on cancel.
func (c *client) invokeCapability(ctx context.Context, capabilityID string, args map[string]any) (any, error) {
	if err := validateCapabilityArgs(capabilityID, args); err != nil {

View on GitHub (pinned to 25830f84bd)