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

  1. Always initialize the entry's OptionalEncryptedValue (use the empty wrapper, not null) before creating a DataStoreEntryNode.
  2. Check how the encrypted value became null — repair or re-save the affected vault entry.
  3. 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

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


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/36049e1645a25731. Report an issue: GitHub.