{"record":{"id":"14ce58f4f72a2cb3","repo":"sipeed/picoclaw","slug":"create-crypto-helper-w","errorCode":null,"errorMessage":"create crypto helper: %w","messagePattern":"create crypto helper: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/matrix/matrix.go","lineNumber":368,"sourceCode":"\t\t\"PRAGMA busy_timeout = 5000\",\n\t}\n\tfor _, pragma := range pragmaStmts {\n\t\tif _, err = db.ExecContext(ctx, pragma); err != nil {\n\t\t\t_ = db.Close()\n\t\t\treturn fmt.Errorf(\"execute %s: %w\", pragma, err)\n\t\t}\n\t}\n\n\t// Wrap with dbutil for dialect support\n\twrappedDB, err := dbutil.NewWithDB(db, sqliteDriver)\n\tif err != nil {\n\t\t_ = db.Close()\n\t\treturn fmt.Errorf(\"wrap database: %w\", err)\n\t}\n\n\tcryptoHelper, err := cryptohelper.NewCryptoHelper(c.client, []byte(c.config.CryptoPassphrase), wrappedDB)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create crypto helper: %w\", err)\n\t}\n\n\tif c.client.DeviceID == \"\" {\n\t\tresp, whoamiErr := c.client.Whoami(ctx)\n\t\tif whoamiErr != nil {\n\t\t\t_ = db.Close()\n\t\t\treturn fmt.Errorf(\"get device ID via whoami: %w\", whoamiErr)\n\t\t}\n\t\tc.client.DeviceID = resp.DeviceID\n\t}\n\n\tif err = cryptoHelper.Init(ctx); err != nil {\n\t\tcryptoHelper.Close()\n\t\treturn fmt.Errorf(\"init crypto helper: %w\", err)\n\t}\n\n\tc.client.Crypto = cryptoHelper\n\tc.cryptoHelper = cryptoHelper","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/matrix/matrix.go#L350-L386","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set a real, non-blank crypto passphrase (strings.TrimSpace it at config load) in the matrix channel config","Verify the Matrix client logged in successfully before initCrypto runs — check the login step's error","Unwrap the returned error to see which argument cryptohelper rejected","Never reuse a crypto DB across passphrases; if you change the passphrase, archive the old crypto DB"],"exampleFix":"# before\n crypto_passphrase: \"   \"  # whitespace-only passes the != \"\" check\n\n# after\n crypto_passphrase: \"a-long-random-secret\"","handlingStrategy":"validation","validationCode":"// before starting the channel\nif strings.TrimSpace(cfg.Matrix.CryptoPassphrase) == \"\" {\n\treturn errors.New(\"matrix crypto_passphrase must be a non-empty secret\")\n}\nif client == nil {\n\treturn errors.New(\"matrix client must be constructed and logged in before crypto init\")\n}","typeGuard":null,"tryCatchPattern":"if err := matrixCh.Start(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"create crypto helper\") {\n\t\t// argument rejection: fix config (passphrase) or client wiring, do not retry\n\t\treturn fmt.Errorf(\"crypto helper misconfigured: %w\", err)\n\t}\n}","preventionTips":["Trim and validate the passphrase at config load, not deep in channel startup","Persist the device_id after first login so crypto init is deterministic","Alert on startup failures containing 'create crypto helper' — they are always config defects"],"tags":["go","matrix","crypto","cryptohelper","configuration","initialization"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}