Skip to content
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

Unhandled Exception: HiveError: This should not happen. Please open an issue on GitHub. #263

Closed
daibao520 opened this issue Mar 27, 2020 · 101 comments · Fixed by #914
Closed
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@daibao520
Copy link

hive version: "1.4.0+1"
This happen when my app crash and restart immediately by android system

E/flutter (32001): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: HiveError: This should not happen. Please open an issue on GitHub.
E/flutter (32001): #0      BinaryReaderImpl.readFrame 
package:hive/…/binary/binary_reader_impl.dart:244
E/flutter (32001): #1      FrameHelper.framesFromBytes 
package:hive/…/binary/frame_helper.dart:15
E/flutter (32001): #2      FrameIoHelper.framesFromFile 
package:hive/…/io/frame_io_helper.dart:36
E/flutter (32001): <asynchronous suspension>
E/flutter (32001): #3      StorageBackendVm.initialize 
package:hive/…/vm/storage_backend_vm.dart:72
E/flutter (32001): <asynchronous suspension>
E/flutter (32001): #4      BoxBaseImpl.initialize 
package:hive/…/box/box_base_impl.dart:82
E/flutter (32001): #5      HiveImpl._openBox 
package:hive/src/hive_impl.dart:85
E/flutter (32001): <asynchronous suspension>
E/flutter (32001): #6      HiveImpl.openBox 
package:hive/src/hive_impl.dart:106
E/flutter (32001): #7      HiveConfigBox.open 
package:liaobei/hive_liaobei/hive_config_box.dart:28
E/flutter (32001): #8      HiveLiaobeiManager.openUserBox 
package:liaobei/hive_liaobei/hive_liaobei_manager.dart:80
E/flutter (32001): <asynchronous suspension>
E/flutter (32001): #9      main 
package:liaobei/main.dart:75
E/flutter (32001): <asynchronous suspension>
E/flutter (32001): #10     _runMainZoned.<anonymous closure>.<anonymous closure>  (dart:ui/hooks.dart:239:25)
E/flutter (32001): #11     _rootRun  (dart:async/zone.dart:1126:13)
E/flutter (32001): #12     _CustomZone.run  (dart:async/zone.dart:1023:19)
E/flutter (32001): #13     _runZoned  (dart:async/zone.dart:1518:10)
E/flutter (32001): #14     runZoned  (dart:async/zone.dart:1502:12)
E/flutter (32001): #15     _runMainZoned.<anonymous closure>  (dart:ui/hooks.dart:231:5)
E/flutter (32001): #16     _startIsolate.<anonymous closure>  (dart:isolate-patch/isolate_patch.dart:307:19)
E/flutter (32001): #17     _RawReceivePortImpl._handleMessage  (dart:isolate-patch/isolate_patch.dart:174:12)
@daibao520 daibao520 added the problem An unconfirmed bug. label Mar 27, 2020
@daibao520
Copy link
Author

When this error happend even i restart app the error still exist

@HeikoMueller
Copy link

HeikoMueller commented May 20, 2020

I run into the same error, also with hive: ^1.4.1+1
Flutter 1.17.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision e6b34c2b5c (3 weeks ago) • 2020-05-02 11:39:18 -0700
Engine • revision 540786dd51
Tools • Dart 2.8.1

2020-05-20 10:36:22.133 20482-20654/com.example.v4 E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: HiveError: This should not happen. Please open an issue on GitHub.
    #0      BinaryReaderImpl.readFrame (package:hive/src/binary/binary_reader_impl.dart:249:7)
    #1      FrameHelper.framesFromBytes (package:hive/src/binary/frame_helper.dart:17:26)
    #2      FrameIoHelper.framesFromFile (package:hive/src/io/frame_io_helper.dart:41:12)
    <asynchronous suspension>
    #3      StorageBackendVm.initialize (package:hive/src/backend/vm/storage_backend_vm.dart:82:30)
    <asynchronous suspension>
    #4      BoxBaseImpl.initialize (package:hive/src/box/box_base_impl.dart:90:20)
    #5      HiveImpl._openBox (package:hive/src/hive_impl.dart:90:17)
    <asynchronous suspension>
    #6      HiveImpl.openBox (package:hive/src/hive_impl.dart:111:18)

@HeikoMueller
Copy link

HeikoMueller commented May 20, 2020

For the moment, I do this as a temporary workaround.

try {
   _box = await Hive.openBox(_boxName);
    } catch(err) {
      /// box could not be opened.
      bool success = false;
      int index = 0;
      while(success == false) {
        _boxName = _boxName + index.toString(); 
        Error _err;   
        try {
          _box = await Hive.openBox(_boxName);
        } catch(err) {
          _err = err;
        }
        if(_err == null) {
          print("Hive box opened with name " + _boxName);
          success = true;
        } else if(index > 100) {
          throw("Hive box could not be opened.");
        }
        index++; 
      }
}

In this provisional way, subfollowing initializations shall find the same new working box name.

However, what is the recommended way to unlock and re-open – or delete – the former box file (in the snippet above "_boxName" without added index) ?

@themisir
Copy link
Contributor

themisir commented Aug 22, 2020

Thanks to @Mr-Martini I can now reproduce the issue.

The issue is caused after using key on unencrypted box or not using key on encrypted box.

To fix the issue we might limit encryptionKey usage on boxes. For example if the box is already encrypted you will not able to pass encryptionKey: null on same box. Or if the box is unencrypted you will not able to use encryptionKey. But I'm not sure where to store box is encrypted or not without changing file structure for boxes.

I just wonder is there any other cases that might cause this issue rather than not using encryption key or using invalid key?

import 'dart:io';
import 'dart:typed_data';

import 'package:hive/hive.dart';

/// Runs some tests
///
/// 1. Opens the box
/// 2. Reads some series of values
/// 3. Writes new values
/// 4. Closes
Future<void> test(int index, [Uint8List key]) async {
  var boxName = 'box_$index';
  var hasKey = key != null;
  var info = '(box = $boxName, hasKey = $hasKey)';

  // open
  Box box;
  try {
    box = await Hive.openBox(boxName, encryptionKey: key);
  } catch (error) {
    return print('Crashed! $info');
  }

  // read
  for (int i = 0; i < 100; i++) {
    var value = box.get('item_$i');
    if (value != null && value != i) {
      print('Item: item_$i Value: $value Expected: $i $info');
    }
  }

  // write
  for (int i = 0; i < 100; i++) {
    await box.put('item_$i', i);
  }

  // close
  await box.close();
  print('OK. $info');
}

void main() async {
  final path = Directory.current.path + '/db';

  Directory(path)
    ..deleteSync(recursive: true)
    ..createSync();

  Hive.init(path);

  var key = Hive.generateSecureKey();

  await test(1, null); // OK
  await test(1, null); // OK
  await test(1, key); // OK, Recovering corrupted box.
  await test(1, null); // Crashes!
}

@Maadhav
Copy link

Maadhav commented Aug 23, 2020

I just started using hive for the first time and started getting this issue. Is there any solution to this. I just reinstalled my app and that fixed.
The error started to come after I started using deleteBoxFromDisk

@knaeckeKami
Copy link

I just wonder is there any other cases that might cause this issue rather than not using encryption key or using invalid key?

I did get this exception a few times from users in my crash reporting and I don't use encryption at all.
I could not reproduce this issue myself yet, though.

@oliverbytes
Copy link

oliverbytes commented Sep 4, 2020

I'm getting the same error. I'm using the background_fetch plugin and I'm re-initializing my Hive boxes on it's BackgroundFetch.registerHeadlessTask() function. So basically, 2 processes (headless and background/foreground) uses 2 Hive instances that open boxes and CRUDing stuffs.

I/flutter (12177): Recovering corrupted box.
W/FlutterEngine(13591): Tried to automatically register plugins with FlutterEngine (io.flutter.embedding.engine.FlutterEngine@738c3e0) but could not find and invoke the GeneratedPluginRegistrant.
I/flutter (13591): Activity (Initial Load) completed in 5002ms
E/flutter (13592): [ERROR:flutter/lib/ui/ui_dart_state.cc(171)] Unhandled Exception: HiveError: This should not happen. Please open an issue on GitHub.
E/flutter (13592): #0      BinaryReaderImpl.readFrame (package:hive/src/binary/binary_reader_impl.dart:249)
E/flutter (13592): #1      FrameHelper.framesFromBytes (package:hive/src/binary/frame_helper.dart:17)
E/flutter (13592): #2      FrameIoHelper.framesFromFile (package:hive/src/io/frame_io_helper.dart:41)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592): #3      StorageBackendVm.initialize (package:hive/src/backend/vm/storage_backend_vm.dart:82)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592): #4      HiveImpl._openBox (package:hive/src/hive_impl.dart:106)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592): #5      HiveImpl.openBox (package:hive/src/hive_impl.dart:135)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592): #6      HiveManager.init (package:app/core/managers/hive.manager.dart:142)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592): #7      init (package:app/core/main/main.dart:43)
E/flutter (13592): <asynchronous suspension>
E/flutter (13592):

@hlongngo
Copy link

hlongngo commented Sep 5, 2020

I have the same error without use encryption to open box.

@marcospsviana
Copy link

I have the same error, but only run the emulator in android 7. When running the emulator in android 9.0 he works very well. Is this anything with the android version?

@themisir themisir added bug Something isn't working more-information-needed Extra information is needed and removed problem An unconfirmed bug. labels Sep 6, 2020
@olenirwing
Copy link

I also have the same error, without using encrypted boxes. Happens when I open a box on start of the app.
We have huge issues because of that because our customers cannot just reinstall the app on the designated devices, or delete the content.
Is there any progress?

@no-response
Copy link

no-response bot commented Sep 20, 2020

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

@no-response no-response bot closed this as completed Sep 20, 2020
@themisir themisir reopened this Sep 20, 2020
@themisir themisir added help wanted Extra attention is needed and removed more-information-needed Extra information is needed labels Sep 20, 2020
@MilosKarakas
Copy link

Hi, I am facing the same issue. It works only for a few initial calls. I am using regular boxes without any encryption. I create a box called 'x' and put a few custom objects for which i have registered the adapters generated by Hive. After saving the data I navigate to another screen, then open the same box, retrieve the data, and it works. But then I navigate back to the initial screen and try to open the box again, and get this:
'Range Error: Not enough bytes available.'.
It happens every single time. I would have though that adapters are making issues, but they are automatically generated and also it does work at the first call.

Do you have any idea what might be happening or provide a possible workaround? I am using Hive in a production ready app, and we are adding offline caching for some features.

@CreamByul
Copy link

CreamByul commented Nov 4, 2021

First of all, thank you for providing a good library.

I have report about this error in Sentry.
It only happens to an unspecified minority after flutter 2.0 migration.
Even after downgrading the flutter version to 1.22.6 again, the problem still persists for users who have encountered this issue.
Worse, the bug doesn't go away even if they completely reinstall the app.
In my code I register all TypeAdapter() after Hive.init() and try openBox. And the issue arises in the process of opening the first box.
I tried updating after deleting pub-cache and reinstalling hive library, but the bug still existed.

The difference between my problem and others is that the problem number of typeId is 18.
There are only 5 typeId from 0 to 5 that I use. And I know that Hive is internally reserved for numbers up to 32.
But isn't it very strange that the issue of HiveError: Cannot read, unknown typeId: 18. Did you forget to register an adapter? occurs? about typeId: 18?

I'm on my last try
If an error occurs, run Hive.ignoreTypeId(18); and run openBox again, and it is under review in the store.
I will update here whether the bug has been fixed after the update.

I've been using Hive for a long time with no problems, but I haven't been able to resolve this issue since it happened and I'm losing hope.
I leave a detailed description of the bug in hopes that the problem will be resolved.

HiveError
HiveError: Cannot read, unknown typeId: 18. Did you forget to register an adapter?
binary_reader_impl.dart in BinaryReaderImpl.read
binary_reader_impl.dart in BinaryReaderImpl.readList
binary_reader_impl.dart in BinaryReaderImpl.read
habit_data_model.g.dart in HabitDataModelAdapter.read
binary_reader_impl.dart in BinaryReaderImpl.read
binary_reader_impl.dart in BinaryReaderImpl.readFrame
frame_helper.dart in FrameHelper.framesFromBytes
frame_io_helper.dart in FrameIoHelper.framesFromFile

Edited on 2021-11-24 16:32
No feedback from users, so I'm only now leaving a result comment.
As Sentry continues to report these bugs, I have concluded that the bug has not been resolved.

@themisir
Copy link
Contributor

themisir commented Nov 4, 2021

Hey @CreamByul ,

Have you modified your models before publishing the update? By update I mean have you did one or more of those options:

  • Changed type id for an existing model
  • Changed field id for an existing model field
  • Changed type of an existing model field (eg: @HiveField(1) String years -> @HiveField(1) int years)
  • Removed any model
  • Removed a field from an existing model and added a new field with same type id (it's same as changing field type actually)

@CreamByul
Copy link

CreamByul commented Nov 4, 2021

Thanks for the reply @themisir,

  1. Changed type id for an existing model
    -> I didn't modify anything like adding, modifying, or deleting typeids.

  2. Changed field id for an existing model field
    -> The existing field id is also not modified at all.

  3. Changed type of an existing model field (eg: @HiveField(1) String years -> @HiveField(1) int years)
    -> I also did not change the type of the existing model field.
    However, when migrating to flutter 2.0, I added 3 fields to my existing model. Each field type is bool, bool, int.
    When I rolled back to 1.22.6, I removed those fields, but the bug still existed.

  4. Removed any model
    -> No.

  5. Removed a field from an existing model and added a new field with same type id (it's same as changing field type actually)
    -> As in answer 3, I did not change the existing fields. I added new fields (migration flutter 2.0) and deleted them (rollback flutter 1.22.6), but the bug was still there. And the bug is that, as mentioned in the first question, the bug occurs even if the user who suffers from the bug completely reinstalls the app.
    In my case, unlike others, it doesn't seem to have anything to do with whether the box already exists.

Finally, the model with 3 fields added and deleted operations is not a buggy Box.
I haven't checked yet as to whether changing the openBox order causes the same bug.


This is the list of versions I use.
flutter: 1.22.6
hive: ^1.4.4+1
hive_generator: ^0.8.2

Thank you for quick response.

@ghost
Copy link

ghost commented Nov 25, 2021

Got the same error.

Screenshot 2021-11-25 at 19 52 25
Basically use the example here from the doc.

Or without encryption:

Screenshot 2021-11-25 at 20 11 04

 hive: ^2.0.4
 hive_flutter: ^1.1.0
 hive_generator: ^1.1.1

@jaesam
Copy link

jaesam commented Dec 2, 2021

Have you modified your models before publishing the update? By update I mean have you did one or more of those options: Changed type id for an existing model
Changed field id for an existing model field
Changed type of an existing model field (eg: @HiveField(1) String years -> @HiveField(1) int years)
Removed any model
Removed a field from an existing model and added a new field with same type id (it's same as changing field type actually)

In my case I did modify one of the existing id. What I had to do was to wrap the problematic openBox with try/catch and on HiveError I refreshed the box by delete the box from the disk and reopen the box (Do this only if the data persisted in the box are not important).

@yasargil
Copy link

yasargil commented Dec 6, 2021

We have the same error, it fails randomly only on android devices until now. We do not have isolate or any other background handlers.

@Sorunome
Copy link
Contributor

Sorunome commented Dec 6, 2021

After digging a lot into hive and these corruption errors, it turns out that hive never itself invokes .flush() to flush the written changes to disk. This works well, as long as the operating system doesn't abruptly kill the app (thanks iOS), your phone does not run out of battery (thanks physics) or thelike. If such things happen, it easily leads to database corruption, resulting in the error mentioned here when attempting to open the database again.

Made a pull request #852 to add a .flush() method to boxes, which you'd still have to manually invoke after writing (put / delete) data to a box.

So, why make .flush() a separate thing and not auto-invoke it? Well, the reason is performance: If you have multiple writes to a box at once, it is sufficient to call .flush() only once after all those writes are done, no need to call it for every single one.

@anandsubbu007
Copy link

how to recover data from this corrupted box?

@Sorunome
Copy link
Contributor

Sorunome commented Dec 9, 2021

how to recover data from this corrupted box?

the box being corrupted you can't really. thus you have to prevent corruptions from happening in the first place instead

@VJag
Copy link

VJag commented Dec 10, 2021

Hi,

We are facing the same issue. i.e Unhandled Exception: HiveError: This should not happen. Please open an issue on GitHub.

May I propose the following changes in the implementation so that crash recovery can be leveraged?

Proposed changes:

Change 1. Introduce a new Error specific to Box corruption that extends HiveError and this will have a field to set the offset of the invalid frame, and the value for this should be the same as recoveryOffset in StorageBackendVm

class HiveBoxCorruptionError extends HiveError {

// offSet of the frame that caused the error
final int offset;

/// Create a new Hive error (internal)
HiveBoxCorruptionError(this.message, this.offset) {
super(message);
}
}

Change 2. Changes in "StorageBackendVm" to catch HiveBoxCorruptionError and make use of the offset

try {

  if (!lazy) {
    recoveryOffset =
    await _frameHelper.framesFromFile(path, keystore, registry, _cipher);
  } else {
    recoveryOffset = await _frameHelper.keysFromFile(path, keystore, _cipher);
  }

} on HiveBoxCorruptionError catch(error) {
     if(_crashRecovery) {
         recoveryOffset = error.offSet;
      } else {
         rethrow;
      }
}

Change 3: Let BinaryReaderImpl throw HiveBoxCorruptionError when frameLength is < 8 etc..

Note: Please don't give too much attention to the syntax. I hope the core idea is clear.

@leisim Please let me know your thoughts?

@anandsubbu007
Copy link

anandsubbu007 commented Dec 21, 2021

u can't really. thus you have to prevent corruptions from happening in the first place instead

App is running fine for around 5 months.
I don't know how it occurs.
is there any specific reason?
how do I need to prevent it from happening again?

@robman70
Copy link

For the moment, I do this as a temporary workaround.

try {
   _box = await Hive.openBox(_boxName);
    } catch(err) {
      /// box could not be opened.
      bool success = false;
      int index = 0;
      while(success == false) {
        _boxName = _boxName + index.toString(); 
        Error _err;   
        try {
          _box = await Hive.openBox(_boxName);
        } catch(err) {
          _err = err;
        }
        if(_err == null) {
          print("Hive box opened with name " + _boxName);
          success = true;
        } else if(index > 100) {
          throw("Hive box could not be opened.");
        }
        index++; 
      }
}

In this provisional way, subfollowing initializations shall find the same new working box name.

However, what is the recommended way to unlock and re-open – or delete – the former box file (in the snippet above "_boxName" without added index) ?

Same problem here. This (strange) workaround worked for me, thanks. :-)

@SimpleTracker
Copy link

SimpleTracker commented Jan 25, 2022

Encountered this issues, and it remains even after I rollback my codes to previous versions. Tried different ways above but did not work. Finally I changed the flutter sdk version and it seems working. The 'Type 18' issue and 'this should not happened' issue has not appeared ever since -- I hope it will not appear any more.

Call-out: I HAVE NOT MIGRATED TO SOUND NULL-SAFTY YET, that's why I can change the sdk version to lower.

in pubyaml.spec, I changed the sdk version from >=2.7.0 to >=2.0.0;

environment:
#  sdk: ">=2.7.0 <3.0.0"
  sdk: ">=2.0.0 <3.0.0"

then flutter pub get

!!!EDIT: This does not work. My App crashed in internal testing.

@SimpleTracker
Copy link

Hi Friends,
Anyone knows if Is this resolved in the latest version(2.0.5)? I really love Hive!
Thank you!

@WatchDogsDev
Copy link

Is this project maintained anymore ?!

@themisir
Copy link
Contributor

Is this project maintained anymore ?!

Yeah it is. But you might ask why this issue haven't yet fixed?

Well, because we didn't found any root cause. I did spend quite a bit of time to try doing lots of stuff with it but didn't found any way to reproduce. This issue usually occurs when models modified without respecting previous model state, or when device kills app during saving process which in both cases causes database file to get corrupted.

I can't fix it if I don't know what really causes this issue, maybe there's something wrong in this library causes this issue. But I myself used hive in production for about 2 year in multiple apps and haven't encountered with this issue. So I really don't know what else can I do for now. If anyone does have any suggestion, I would be happy to work on it.

@miguelflores1993
Copy link

¿Este proyecto se mantiene más?

Sí lo es. Pero puede preguntar por qué este problema aún no se ha solucionado.

Bueno, porque no encontramos ninguna causa raíz. Pasé bastante tiempo tratando de hacer muchas cosas con él, pero no encontré ninguna forma de reproducirlo. Este problema generalmente ocurre cuando los modelos se modifican sin respetar el estado del modelo anterior, o cuando el dispositivo elimina la aplicación durante el proceso de guardado, lo que en ambos casos hace que el archivo de la base de datos se corrompa.

No puedo solucionarlo si no sé qué causa realmente este problema, tal vez haya algo mal en esta biblioteca que cause este problema. Pero yo mismo usé Hive en producción durante aproximadamente 2 años en varias aplicaciones y no me he encontrado con este problema. Así que realmente no sé qué más puedo hacer por ahora. Si alguien tiene alguna sugerencia, estaré encantado de trabajar en ella.

I tell you that this is happening to me in production on many phones in the A50, A70 sasumng.
I receive many stays and the error is the same

@maRci002
Copy link
Contributor

Hello guys, I made a PR to resolve this issue #914

Let me know if it works.

@zmoshansky
Copy link

Hopefully the following can all be closed too:

#883
#872
#848
#841
#810
#803
#780
#639
#624

@themisir
Copy link
Contributor

Fix published with hive v2.0.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.