isar / hive

Lightweight and blazing fast key-value database written in pure Dart.
Apache License 2.0
4.02k stars 401 forks source link

Unhandled Exception: type 'Account' is not a subtype of type 'Order' of 'obj' #568

Open tomasweigenast opened 3 years ago

tomasweigenast commented 3 years ago

I got this error when I try to save an Account to a box:

E/flutter (19165): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'Account' is not a subtype of type 'Order' of 'obj'
E/flutter (19165): #0      OrderAdapter.write (package:distribuidora_griwert_distributors/application/data_source/adapters/order_adapter.dart)
package:distribuidora_griwert_distributors/…/adapters/order_adapter.dart:1
E/flutter (19165): #1      BinaryWriterImpl.write
package:hive/…/binary/binary_writer_impl.dart:316
E/flutter (19165): #2      BinaryWriterImpl.writeFrame
package:hive/…/binary/binary_writer_impl.dart:254
E/flutter (19165): #3      StorageBackendVm.writeFrames.<anonymous closure>
package:hive/…/vm/storage_backend_vm.dart:123
E/flutter (19165): #4      ReadWriteSync.syncWrite.<anonymous closure>
package:hive/…/vm/read_write_sync.dart:26

It seems like Hive is getting the wrong adapter. Accountand Order are classes that have their corresponding adapter. They are registered in the following order: OrderAdapter(), AccountAdapter(). If I invert the order, the exception is the same when I try to save an Order type.

I have a wrapper around Hive.registerAdapter to register them like:

await Storage.instance.init(options: StorageOptions(
      adapters: [OrderAdapter(), AccountAdapter()]
    ));

And then:

 if(options != null) {

      // Register Hive adapters
      if(options.adapters != null && options.adapters.length > 0) {
        options.adapters.forEach((adapter) => Hive.registerAdapter(adapter));
      }
    }

    Hive.init(getAppDataPath("hive"));

Adapters are registered before Hive.init()

themisir commented 3 years ago

You've probably used same typeId for multiple types.

kirill-plotnikov commented 3 years ago

You've probably used same typeId for multiple types.

Same problem. image

kirill-plotnikov commented 3 years ago

You've probably used same typeId for multiple types.

Same problem. image

I hope this information helps someone. I reinstall the app - everything worked. I guess it was corrupted data.

btw can i erase all the hive data from device with internal hive library methods?

themisir commented 3 years ago

btw can i erase all the hive data from device with internal hive library methods?

Yes, there's a method called deleteFromDisk().

mohammadne commented 3 years ago

same problem

kirill-plotnikov commented 3 years ago

same problem

Try to define adapter type when register it. Hive.registerAdapter<TypeOfAdapterHere>(adapter))

mohammadne commented 3 years ago

same problem

Try to define adapter type when register it. Hive.registerAdapter<TypeOfAdapterHere>(adapter))

yes, that's it. but is there any way to register list of TypeAdapter in place, like :

adapters.forEach((adapter) => Hive.registerAdapter(adapter));
mohammadne commented 3 years ago
Map<dynamic, TypeAdapter> adapters = {
FirstType: FirstTypeAdapter,
SecondType: SecondTypeAdapter
}
adapters.forEach((k,v) => Hive.registerAdapter<k>(v));

will get :

The name 'k' isn't a type so it can't be used as a type argument.
kirill-plotnikov commented 3 years ago
Map<dynamic, TypeAdapter> adapters = {
FirstType: FirstTypeAdapter,
SecondType: SecondTypeAdapter
}
adapters.forEach((k,v) => Hive.registerAdapter<k>(v));

will get :

The name 'k' isn't a type so it can't be used as a type argument.

Yes, it was a stupid suggestion) Sorry.