xpipe-io/xpipe · error · IllegalArgumentException
Encrypted value is null
Error message
Encrypted value is null
What it means
DataStoreEntryNode wraps an OptionalEncryptedValue that holds a store's serialized data, and its constructor requires a non-null wrapper. Passing null throws IllegalArgumentException — the node cannot represent an entry without its (possibly empty) encrypted value container.
Source
Thrown at app/src/main/java/io/xpipe/app/storage/DataStoreEntryNode.java:38
var type = TypeFactory.createDefaultInstance().constructParametricType(OptionalEncryptedValue.class, clazz);
OptionalEncryptedValue<T> enc = JacksonMapper.getDefault().readValue(file.toFile(), type);
return enc != null ? new DataStoreEntryNode<>(enc, true) : null;
}
public static <T> DataStoreEntryNode<T> of(T value) {
return value != null ? new DataStoreEntryNode<>(OptionalEncryptedValue.ofRaw(value), false) : null;
}
public static <T> DataStoreEntryNode<T> ofWritten(T value) {
return value != null ? new DataStoreEntryNode<>(OptionalEncryptedValue.ofRaw(value), true) : null;
}
private final OptionalEncryptedValue<T> enc;
private boolean written;
private DataStoreEntryNode(OptionalEncryptedValue<T> enc, boolean written) {
if (enc == null) {
throw new IllegalArgumentException("Encrypted value is null");
}
this.enc = enc;
this.written = written;
}
public T reparseValue(Class<T> clazz) {
var newValue = enc.reparseValue(clazz);
// Keep existing object if possible
return Objects.equals(enc.getValue(), newValue) ? enc.getValue() : newValue;
}
public DataStoreEntryNode<T> prepareForWrite(DataStoreEntry entry, boolean encryptIfRestricted, T newValue) {
var targetScope = DataStoreAccessScope.getTargetScope(entry.getAccessScope());
var currentScope = enc.getSecret() != null ? enc.getSecret().getScope() : targetScope;
var shouldEncrypt = (encryptIfRestricted && targetScope.isAccessSubRestricted())
|| AppPrefs.get().encryptAllVaultData().get();View on GitHub (pinned to d85ca821ba)
Solutions
- Always initialize the entry's OptionalEncryptedValue (use the empty wrapper, not null) before creating a DataStoreEntryNode.
- Check how the encrypted value became null — repair or re-save the affected vault entry.
- Construct nodes only via DataStoreEntryNode.of(...) and ensure that path never receives null.
Example fix
// before DataStoreEntryNode.of(entry.getEncryptedValue()); // NPE-ish throw when null // after var enc = entry.getEncryptedValue() != null ? entry.getEncryptedValue() : OptionalEncryptedValue.empty(); DataStoreEntryNode.of(enc);
Defensive patterns
Strategy: type-guard
Validate before calling
if (entry.getEncryptedValue() == null) {
entry.setEncryptedValue(OptionalEncryptedValue.empty());
} Type guard
boolean nodeReady(DataStoreEntry e) { return e.getEncryptedValue() != null; } Try / catch
try {
DataStoreEntryNode.of(enc);
} catch (IllegalArgumentException e) {
// rebuild the node from an empty encrypted value
} Prevention
- Never store null for the encrypted-value wrapper; use an empty instance.
- Validate vault JSON on load and repair missing encrypted-value fields.
- Always go through the official factory methods instead of direct construction.
When it happens
Trigger: Calling the private factory DataStoreEntryNode.of(...) path / constructor with a null OptionalEncryptedValue, e.g. when serializing a DataStoreEntry whose encrypted-value field was never initialized or was lost during deserialization of a corrupted vault node.
Common situations: Vault JSON where the encrypted value field is absent/null for an entry; entries loaded from an older format or partially failed migration; code constructing entry nodes directly instead of through the official factory.
Related errors
- Unable to change scope from raw value with null value
- Principals must not be empty
- Name is empty
- Secret is not accessible
- Trimmed entry name is empty
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/36049e1645a25731.
Report an issue: GitHub.