{"record":{"id":"cc3ba0c00d26f726","repo":"chenhg5/cc-connect","slug":"device-id-not-available-from-whoami","errorCode":null,"errorMessage":"device ID not available from whoami","messagePattern":"device ID not available from whoami","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/matrix/e2ee.go","lineNumber":170,"sourceCode":"\t// Bootstrap cross-signing\n\tp.setupCrossSigning(ctx, ch)\n\n\t// client.Crypto must be set for VerificationHelper\n\tclient.Crypto = ch\n\n\t// Initialize SAS verification helper\n\tif p.autoVerify {\n\t\tif vErr := p.initVerification(ctx, ch); vErr != nil {\n\t\t\tslog.Warn(\"matrix: verification helper not available\", \"error\", vErr)\n\t\t} else {\n\t\t\tslog.Info(\"matrix: SAS verification enabled\", \"mode\", \"auto-verify\")\n\t\t}\n\t}\n}\n\nfunc (p *Platform) initCrypto(ctx context.Context, client *mautrix.Client) (*cryptohelper.CryptoHelper, error) {\n\tif client.DeviceID == \"\" {\n\t\treturn nil, fmt.Errorf(\"device ID not available from whoami\")\n\t}\n\n\thomeDir, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get home dir: %w\", err)\n\t}\n\tcryptoDir := filepath.Join(homeDir, \".cc-connect\")\n\tif err := os.MkdirAll(cryptoDir, 0o700); err != nil {\n\t\treturn nil, fmt.Errorf(\"create data dir: %w\", err)\n\t}\n\tdbPath := filepath.Join(cryptoDir, fmt.Sprintf(\"matrix-crypto-%s.db\", client.DeviceID))\n\n\t// Derive a stable pickle key from the access token\n\th := sha256.Sum256([]byte(p.accessToken))\n\tpickleKey := make([]byte, 32)\n\tcopy(pickleKey, h[:])\n\n\treturn p.tryInitCrypto(ctx, client, pickleKey, dbPath, false)","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/matrix/e2ee.go#L152-L188","documentation":"initCrypto in platform/matrix/e2ee.go:170 requires a device ID to set up end-to-end encryption, but client.DeviceID is empty after whoami. The library throws \"device ID not available from whoami\" because the Matrix crypto helper cannot be keyed without a device ID.","triggerScenarios":"Calling initE2EE when the mautrix client was constructed with access-token login (whoami) that did not yield a device_id — e.g. token obtained outside the library, no device_id field in the whoami response, or server omitting it.","commonSituations":"Using a pre-existing access token created without a device_id (e.g. from an older login or manual curl); Matrix homeserver versions that omit device_id in whoami responses; logging in via a custom flow instead of mautrix's Login API.","solutions":["Log in via mautrix's Login API with DeviceID set (e.g. client.Login with ReqLogin{DeviceID: ...}) instead of relying on whoami","Supply an explicit device ID in the client configuration (mautrix.NewClient with DeviceID param)","Disable E2EE if a device ID cannot be obtained (skip initE2EE) and run without encryption","Check homeserver whoami response actually includes device_id (server-side config/version issue)"],"exampleFix":"// before\nclient, _ := mautrix.NewClient(homeserver, \"\", token)\nclient.DeviceID = \"\" // set from whoami, may be empty\n// after\nclient, _ := mautrix.NewClient(homeserver, \"\", token)\nif client.DeviceID == \"\" {\n    client.DeviceID = id.DeviceID(cfg.MatrixDeviceID) // from config/login\n}","handlingStrategy":"validation","validationCode":"if client.DeviceID == \"\" {\n    return errors.New(\"e2ee requires a device ID; set it via login or config before enabling e2ee\")\n}","typeGuard":"func hasDeviceID(c *mautrix.Client) bool { return c != nil && c.DeviceID != \"\" }","tryCatchPattern":"crypto, err := p.initCrypto(ctx, client)\nif err != nil {\n    if strings.Contains(err.Error(), \"device ID not available\") {\n        slog.Warn(\"E2EE disabled: no device ID from whoami; re-login to obtain one\")\n        return nil // degrade gracefully without encryption\n    }\n    return fmt.Errorf(\"init e2ee: %w\", err)\n}","preventionTips":["Obtain the access token through mautrix's Login API so device_id is always set","Persist the device ID in config and reuse it across restarts","Verify whoami response includes device_id when using external tokens","Treat missing device ID as a config error surfaced at startup, not at first message"],"tags":["matrix","e2ee","device-id","crypto"],"backgroundTag":"missing-required-config-field","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}