Issue
I have such a code. But I am getting _CastError (Null check operator used on a null value)
error in the codes.
const secureStorage = FlutterSecureStorage();
final encryprionKey = secureStorage.read(key: 'key');
if (encryprionKey == null) {
final key = Hive.generateSecureKey();
await secureStorage.write(
key: 'key',
value: base64UrlEncode(key),
);
}
final key = await secureStorage.read(key: 'key');
final encryptionKey = base64Url.decode(key!);
print('Encryption key: $encryptionKey');
final encryptedBox= await Hive.openBox('vaultBox', encryptionCipher:
HiveAesCipher(encryptionKey));
encryptedBox.put('secret', 'Hive is cool');
print(encryptedBox.get('secret'));
How can I solve it?
Solution
final encryprionKey = secureStorage.read(key: 'key');
neglects to await
the result of the secureStorage.read
. The returned Future
itself is never null
, so the if (encryprionKey == null)
check is never true, nothing is ever written, and the second secureStorage.read
call (which is await
ed) will get back null
.
This is why the Dart analyzer warned you that the if (encryprionKey == null)
condition is always false. Enabling the unawaited_futures
lint would have generated an additional (and perhaps clearer) warning.
Not having separate variables for the two calls to secureStorage.read
also would have caught this as a compilation error:
const secureStorage = FlutterSecureStorage();
var encryprionKey = secureStorage.read(key: 'key');
if (encryprionKey == null) {
final key = Hive.generateSecureKey();
await secureStorage.write(
key: 'key',
value: base64UrlEncode(key),
);
}
// This line would have generated a TypeError.
encryprionKey = await secureStorage.read(key: 'key');
In this case, it'd better to reassign the encryprionKey
(sic) variable than to make it final
with a separate key
variable. Having separate variables to represent the same thing is more confusing and is error-prone.
Answered By - jamesdlin
Answer Checked By - Pedro (JavaFixing Volunteer)