Skip to content

Error: DomException IdbKeyRangeMakeError (0): Creating key range failed #4675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bigg-S opened this issue Feb 1, 2025 · 2 comments
Closed
Labels
A-Developer-Experience A-Element-R Issues affecting the port of Element's crypto layer to Rust T-Defect

Comments

@bigg-S
Copy link

bigg-S commented Feb 1, 2025

Issue: IdbKeyRangeMakeError when using fake-indexeddb with initRustCrypto

Description

I'm encountering an error when trying to initialize the crypto backend using initRustCrypto while using an in-memory IndexedDB from the fake-indexeddb package. The error occurs specifically when calling this.client.initRustCrypto().

Error Message

[0] Checking key backup status...
[0] FetchHttpApi: --> GET https://matrix.beeper.com/_matrix/client/v3/room_keys/version
[0] /node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/index.js:10194
[0]     const ret = new Error(getStringFromWasm0(arg0, arg1));
[0]                 ^
[0] 
[0] Error: DomException IdbKeyRangeMakeError (0): Creating key range failed
[0]     at module.exports.__wbindgen_error_new (/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/index.js:10194:17)
[0]     at matrix_sdk_crypto_wasm.wasm.<T as futures_util::fns::FnOnce1<A>>::call_once::h05d72edafa394dd0 (wasm://wasm/matrix_sdk_crypto_wasm.wasm-01906b8e:wasm-function[6552]:0x3af412)
[0]     at matrix_sdk_crypto_wasm.wasm.<futures_util::fns::MapErrFn<F> as futures_util::fns::FnOnce1<core::result::Result<T,E>>>::call_once::h0b79ccf2b4c2a322 (wasm://wasm/matrix_sdk_crypto_wasm.wasm-01906b8e:wasm-function[8123]:0x3d9f51)
[0]     at matrix_sdk_crypto_wasm.wasm.matrix_sdk_crypto_wasm::future::future_to_promise_with_custom_error::{{closure}}::{{closure}}::h4c8a1194d1f31297 (wasm://wasm/matrix_sdk_crypto_wasm.wasm-01906b8e:wasm-function[1580]:0x270040)
[0]     at matrix_sdk_crypto_wasm.wasm.wasm_bindgen_futures::queue::Queue::new::{{closure}}::h84ce96b9c85cc796 (wasm://wasm/matrix_sdk_crypto_wasm.wasm-01906b8e:wasm-function[1468]:0x2380a2)
[0]     at matrix_sdk_crypto_wasm.wasm.wasm_bindgen::convert::closures::invoke1_mut::h8343de5045287dec (wasm://wasm/matrix_sdk_crypto_wasm.wasm-01906b8e:wasm-function[9368]:0x3ed3c2)
[0]     at __wbg_adapter_65 (/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/index.js:261:10)
[0]     at real (node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/index.js:203:20)
[0]     at node:internal/process/task_queues:151:7
[0]     at AsyncResource.runInAsyncScope (node:async_hooks:211:14)

I don't know why I am running into this error and how I can correct it. Any help is much appreciated.

Here is the relevant part of my code:

async initialize(): Promise<{token: string}> {
    if(this.client !== null) {
      return {token: this.accessToken};
    }

    if (this.isInitializing) {
      console.log('Matrix client initialization in progress.');
      return {token: this.accessToken};
    }

    if (this.isInitialized) {
      console.log('Matrix client already initialized.');
      return {token: this.accessToken};
    }

    this.isInitializing = true;

    try {
      const dbName = `matrix-js-sdk:${this.authConfig.username}`;

      this.client = MatrixSDK.createClient({
        baseUrl: this.authConfig.domain,
        userId: `@${this.authConfig.username}:${this.authConfig.domain}`,
        deviceId: this.generateDeviceId(),
        cryptoStore: new MatrixSDK.IndexedDBCryptoStore(indexedDB, dbName)
      });

      if(!this.client.isLoggedIn()) {
        await this.login();
      }

      await this.setupCrypto();
      await this.setupEventListeners();

      if(!this.client.clientRunning) {
        await this.client.startClient({initialSyncLimit: 500, lazyLoadMembers: true})
        await this.initialFetch();
      }

      const syncToken = await this.client.store.getSavedSyncToken();

      await updateSyncToken(syncToken ?? "");

      this.isInitialized = true;
      console.log('Matrix client fully initialized.');

      return {token: this.accessToken};
    } catch (error: any) {
      console.error('Failed to initialize Matrix client:', error);
      this.client = null;
      throw error;
    } finally {
      this.isInitializing = false;
    }
  }


private async setupCrypto(): Promise<void> {
    if (!this.client) {
      throw new Error('Client not created');
    }

    for (const dbType of ["indexeddb", "memory"]) {
      try {
        const promise = this.client.store.startup();
        console.log("MatrixClientPeg: waiting for MatrixClient store to initialise");
        await promise;
        break;
      } catch (err) {
        if (dbType === "indexeddb") {
          console.error("Error starting matrixclient store - falling back to memory store", err);
          this.client.store = new MatrixSDK.MemoryStore({
            localStorage: localStorage,
          });
        } else {
          console.error("Failed to start memory store!", err);
          throw err;
        }
      }
    }
    
    this.client.store.on?.("closed", this.onUnexpectedStoreClose);

    this.cryptoManager = new CryptoManager(this.client);

    const cryptoStatus = await this.cryptoManager.isCryptoReady();

    // initialize crypto if not fully ready
    if (!cryptoStatus.crossSigningReady || !cryptoStatus.secretStorageReady) {
      try {
        await this.cryptoManager.initializeCrypto({
          password: this.authConfig.password,
          setupCrossSigning: true,
          setupSecretStorage: true,
          authConfig: this.authConfig
        });
      } catch (error) {
        console.error('Failed to initialize crypto:', error);
        throw error;
      }
    }

    // ensure key backup is set up
    const cryptoApi = this.client.getCrypto();
    if (cryptoApi) {
      const keyBackupInfo = await cryptoApi.checkKeyBackupAndEnable();

      if (!keyBackupInfo) {
        await cryptoApi.resetKeyBackup();
      }

      // event listener for key backup status (optional)
      this.client.on(MatrixSDK.Crypto.CryptoEvent.KeyBackupStatus, async (status) => {
        try {
          await setKeyBackupStatus(status);
        } catch (error) {
          console.error('Failed to update key backup status:', error);
        }
      });
    }
  }

\async initializeCrypto(opts?: {
    password?: string;
    setupCrossSigning?: boolean;
    setupSecretStorage?: boolean;
    authConfig?: UserPayload;
  }): Promise<CryptoSetupStatus> {
    
    if (!this.client) {
      throw new Error("createClient must be called first");
    }

    this.client.getUserId()?.replace(/^(.+?):https:\/\/matrix\.(.+)$/, '$1:$2') || '';

    await this.client.initRustCrypto();

    const crypto = this.client.getCrypto();
    if (!crypto) {
      throw new Error('Crypto not initialized');
    }

    try {
      // bootstrap cross-signing if requested
      if (opts?.setupCrossSigning) {
        await crypto.bootstrapCrossSigning({
          authUploadDeviceSigningKeys: async (makeRequest) => {
            const { username, password } = opts.authConfig as UserPayload;
            const authData: AuthDict = {
              type: AuthType.Password,
              identifier: { type: "m.id.user", username },
              password,
              session: "",
            };
            return makeRequest(authData).then(() => {});
          },
        });
      }

      // bootstrap secret storage if requested
      if (opts?.setupSecretStorage) {
        await crypto.bootstrapSecretStorage({
          // create new secret storage key (if needed)
          setupNewSecretStorage: true,
          ...(opts.password ? {
            createSecretStorageKey: async () => {
              return crypto.createRecoveryKeyFromPassphrase(opts.password);
            }
          } : {})
        });
      }

      // verify the current device
      await this.verifyCurrentDevice();

      // return current crypto status
      return this.isCryptoReady();
    } catch (error) {
      console.error('Crypto initialization error:', error);
      throw error;
    }
  }
@dosubot dosubot bot added A-Developer-Experience A-Element-R Issues affecting the port of Element's crypto layer to Rust T-Defect labels Feb 1, 2025
@t3chguy
Copy link
Member

t3chguy commented Feb 3, 2025

This sounds like an issue with https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/ & fake-indexeddb, might be worth reporting there.

@richvdh
Copy link
Member

richvdh commented Feb 3, 2025

Duplicate of matrix-org/matrix-rust-sdk-crypto-wasm#196

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Developer-Experience A-Element-R Issues affecting the port of Element's crypto layer to Rust T-Defect
Projects
None yet
Development

No branches or pull requests

3 participants