sipeed/picoclaw · error

create crypto helper: %w

Error message

create crypto helper: %w

What it means

Thrown by MatrixChannel.initCrypto when cryptohelper.NewCryptoHelper (pkg/channels/matrix/matrix.go:368) rejects its arguments while constructing the mautrix crypto helper that persists Olm/Megolm sessions in the SQLite DB. The helper encrypts the stored Olm account with a pickle key derived from config.CryptoPassphrase. It errors when the mautrix client is nil, the pickle key/passphrase is empty, or the wrapped DB is nil. Note initCrypto is only called when CryptoPassphrase != "" (matrix.go:271), so a whitespace-only passphrase or a failed client construction are the realistic causes.

Source

Thrown at pkg/channels/matrix/matrix.go:368

		"PRAGMA busy_timeout = 5000",
	}
	for _, pragma := range pragmaStmts {
		if _, err = db.ExecContext(ctx, pragma); err != nil {
			_ = db.Close()
			return fmt.Errorf("execute %s: %w", pragma, err)
		}
	}

	// Wrap with dbutil for dialect support
	wrappedDB, err := dbutil.NewWithDB(db, sqliteDriver)
	if err != nil {
		_ = db.Close()
		return fmt.Errorf("wrap database: %w", err)
	}

	cryptoHelper, err := cryptohelper.NewCryptoHelper(c.client, []byte(c.config.CryptoPassphrase), wrappedDB)
	if err != nil {
		return fmt.Errorf("create crypto helper: %w", err)
	}

	if c.client.DeviceID == "" {
		resp, whoamiErr := c.client.Whoami(ctx)
		if whoamiErr != nil {
			_ = db.Close()
			return fmt.Errorf("get device ID via whoami: %w", whoamiErr)
		}
		c.client.DeviceID = resp.DeviceID
	}

	if err = cryptoHelper.Init(ctx); err != nil {
		cryptoHelper.Close()
		return fmt.Errorf("init crypto helper: %w", err)
	}

	c.client.Crypto = cryptoHelper
	c.cryptoHelper = cryptoHelper

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Set a real, non-blank crypto passphrase (strings.TrimSpace it at config load) in the matrix channel config
  2. Verify the Matrix client logged in successfully before initCrypto runs — check the login step's error
  3. Unwrap the returned error to see which argument cryptohelper rejected
  4. Never reuse a crypto DB across passphrases; if you change the passphrase, archive the old crypto DB

Example fix

# before
 crypto_passphrase: "   "  # whitespace-only passes the != "" check

# after
 crypto_passphrase: "a-long-random-secret"
Defensive patterns

Strategy: validation

Validate before calling

// before starting the channel
if strings.TrimSpace(cfg.Matrix.CryptoPassphrase) == "" {
	return errors.New("matrix crypto_passphrase must be a non-empty secret")
}
if client == nil {
	return errors.New("matrix client must be constructed and logged in before crypto init")
}

Try / catch

if err := matrixCh.Start(ctx); err != nil {
	if strings.Contains(err.Error(), "create crypto helper") {
		// argument rejection: fix config (passphrase) or client wiring, do not retry
		return fmt.Errorf("crypto helper misconfigured: %w", err)
	}
}

Prevention

When it happens

Trigger: Configuring matrix crypto with a passphrase of only spaces (passes the != "" guard but yields an empty/invalid pickle key after conversion); the Matrix client being nil because earlier construction/login steps failed silently; passing a nil wrappedDB after a dbutil failure path was ignored.

Common situations: YAML/env config with MATRIX_CRYPTO_PASSPHRASE=' ' from templating; pipeline variables injecting empty strings that become whitespace; refactors that construct MatrixChannel before client login completes.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/14ce58f4f72a2cb3. Report an issue: GitHub.