chenhg5/cc-connect · error
create crypto helper: %w
Error message
create crypto helper: %w
What it means
This error wraps any failure from cryptohelper.NewCryptoHelper() when the Matrix platform adapter initializes its end-to-end-encryption helper. NewCryptoHelper builds a SQL crypto store (pickle key, device identity, olm/megolm machinery) at dbPath; if constructing the store, parsing the user ID, or opening the database fails, the error is wrapped with context and returned to initCrypto, aborting E2EE setup.
Source
Thrown at platform/matrix/e2ee.go:194
}
cryptoDir := filepath.Join(homeDir, ".cc-connect")
if err := os.MkdirAll(cryptoDir, 0o700); err != nil {
return nil, fmt.Errorf("create data dir: %w", err)
}
dbPath := filepath.Join(cryptoDir, fmt.Sprintf("matrix-crypto-%s.db", client.DeviceID))
// Derive a stable pickle key from the access token
h := sha256.Sum256([]byte(p.accessToken))
pickleKey := make([]byte, 32)
copy(pickleKey, h[:])
return p.tryInitCrypto(ctx, client, pickleKey, dbPath, false)
}
func (p *Platform) tryInitCrypto(ctx context.Context, client *mautrix.Client, pickleKey []byte, dbPath string, isRetry bool) (*cryptohelper.CryptoHelper, error) {
ch, err := cryptohelper.NewCryptoHelper(client, pickleKey, dbPath)
if err != nil {
return nil, fmt.Errorf("create crypto helper: %w", err)
}
ch.DBAccountID = client.UserID.String()
if err := ch.Init(ctx); err != nil {
if !isRetry && strings.Contains(err.Error(), "not marked as shared") {
slog.Warn("matrix: stale device keys on server, force-uploading new keys")
func() {
defer func() { recover() }()
if mach := ch.Machine(); mach != nil {
if shareErr := mach.ShareKeys(ctx, -1); shareErr != nil {
slog.Error("matrix: failed to force-share keys", "error", shareErr)
}
}
}()
ch.Close()
client.StateStore = nil
client.Store = mautrix.NewMemorySyncStore()
return p.tryInitCrypto(ctx, client, pickleKey, dbPath, true)View on GitHub (pinned to 4000b2338a)
Solutions
- Ensure the directory containing dbPath exists and is writable by the process (mkdir -p and chown/chmod).
- Verify the dbPath scheme matches an available store backend (e.g. sqlite3 driver compiled in); add the driver import if missing.
- Delete a corrupted crypto store DB and restart to force fresh key upload (the code already handles 'not marked as shared' retries, but corruption may need manual cleanup).
- Regenerate the pickle key and restart the platform so a fresh helper is created.
- Check startup logs for the underlying wrapped error to identify the store-level cause.
Example fix
// before
ch, err := cryptohelper.NewCryptoHelper(client, pickleKey, "/var/lib/cc-connect/crypto.db")
// after
if err := os.MkdirAll("/var/lib/cc-connect", 0o755); err != nil {
return nil, fmt.Errorf("prepare crypto db dir: %w", err)
}
ch, err := cryptohelper.NewCryptoHelper(client, pickleKey, "/var/lib/cc-connect/crypto.db") Defensive patterns
Strategy: try-catch
Validate before calling
// Go: before starting the platform, ensure the crypto DB path is usable
if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil {
return fmt.Errorf("crypto db dir not creatable: %w", err)
}
if f, err := os.OpenFile(dbPath+".probe", os.O_CREATE|os.O_WRONLY, 0o600); err != nil {
return fmt.Errorf("crypto db path not writable: %w", err)
} else { f.Close(); os.Remove(dbPath + ".probe") } Try / catch
plat, err := matrix.New(opts)
if err != nil {
var ctxErr error
if errors.As(err, &ctxErr) && strings.Contains(err.Error(), "create crypto helper") {
slog.Error("E2EE store setup failed — check crypto db path/permissions", "cause", errors.Unwrap(err))
}
return err
} Prevention
- Pre-create and permission the data directory holding the crypto DB in deployment scripts.
- Use an absolute, stable dbPath so restarts reuse the same store.
- Import your SQL driver (e.g. _ "modernc.org/sqlite") before constructing the helper.
- Monitor startup logs for 'create crypto helper' during config changes.
When it happens
Trigger: tryInitCrypto calls cryptohelper.NewCryptoHelper(client, pickleKey, dbPath) and it returns err — e.g. the crypto store database at dbPath cannot be opened/created, the SQL driver is unavailable, the pickle key is invalid/empty in a way the store rejects, or the underlying mautrix client state is inconsistent.
Common situations: The data directory for the crypto DB does not exist or is not writable (read-only filesystem, wrong permissions, container volume not mounted); the configured DB path uses an unsupported sqlstore URI; the pickle key was generated with a broken RNG or reused/corrupted state from a previous run.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- matrix: init verification: %w
- device ID not available from whoami
- get home dir: %w
- create data dir: %w
- init crypto: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/888c4d3ab865b9ce.
Report an issue: GitHub.