chenhg5/cc-connect · error

matrix: client not available

Error message

matrix: client not available

What it means

initVerification aborts E2EE device-verification setup with "matrix: client not available" when getClient() returns nil. Initializing the verification helper requires an authenticated Matrix client to register event handlers and access the crypto machine. Without a live client, verification cannot be set up.

Source

Thrown at platform/matrix/verification.go:202

	// ConfirmSAS must run in a separate goroutine because onVerificationKey
	// holds activeTransactionsLock when calling showSAS, and ConfirmSAS
	// also acquires the same non-reentrant mutex.
	go func() {
		helper := vc.platform.getVerificationHelper()
		if helper == nil {
			return
		}
		if err := helper.ConfirmSAS(context.Background(), txnID); err != nil {
			slog.Error("matrix: confirm SAS failed", "txn_id", txnID, "error", err)
		}
	}()
}

func (p *Platform) initVerification(ctx context.Context, ch *cryptohelper.CryptoHelper) error {
	client := p.getClient()
	if client == nil {
		return fmt.Errorf("matrix: client not available")
	}

	// Wrap the client's actual HTTP transport. We must use client.Client directly
	// (not p.httpClient) because cryptohelper.Init() may have replaced client.Client
	// with a new http.Client instance.
	if client.Client == nil {
		return fmt.Errorf("matrix: client http.Client is nil")
	}
	base := client.Client.Transport
	if base == nil {
		base = http.DefaultTransport
	}
	client.Client.Transport = &encryptingTransport{base: base, p: p}
	slog.Info("matrix: transport wrapped for verification encryption")

	callbacks := &verificationCallbacks{platform: p}
	helper := verificationhelper.NewVerificationHelper(client, ch.Machine(), nil, callbacks, false, false, true)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Make sure Start() successfully created the client before initE2EE runs — check earlier login errors
  2. Verify Matrix credentials/homeserver reachability so the client is actually established
  3. Order the startup sequence so E2EE/verification init happens after client creation
  4. If triggered by a reconnect race, guard initVerification with a connectivity check or retry after reconnect
Defensive patterns

Strategy: type-guard

Validate before calling

if p.getClient() == nil {
    // postpone E2EE init until the client exists
}

Type guard

func e2eeReady(p *Platform) bool { return p.getClient() != nil }

Try / catch

if err := p.initVerification(ctx, ch); err != nil {
    if strings.Contains(err.Error(), "client not available") {
        // retry after (re)connect
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: initE2EE calls initVerification before the client is assigned (startup ordering issue), or after clearClient() nulled it (connection lost), so getClient() == nil at the start of initVerification.

Common situations: E2EE enabled in config but the initial login/sync failed, leaving the client nil; a race between connection teardown and E2EE initialization during a reconnect cycle.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a422fcd8a32dbda9. Report an issue: GitHub.