xpipe-io/xpipe · error · IllegalArgumentException
Unable to change scope from raw value with null value
Error message
Unable to change scope from raw value with null value
What it means
OptionalEncryptedValue.with(value, secret, scope) refuses to apply a scope change to a value that has no encrypted content (value == null) but is currently a raw value, because with null content there is no secret object to re-encrypt and a raw value cannot itself carry a scope restriction. The library throws IllegalArgumentException since the argument combination (null value + raw value + new scope) is invalid.
Source
Thrown at app/src/main/java/io/xpipe/app/secret/OptionalEncryptedValue.java:89
public OptionalEncryptedValue<T> withUpdatedPrincipals() {
return with(
value,
isEncrypted() ? DataStoreAccessScope.getTargetScope(getSecret().getScope()) : null);
}
public OptionalEncryptedValue<T> with(T value, DataStoreAccessScope scope) {
if (value == null && scope == null) {
return null;
}
var encryptionUnchanged = (secret == null && scope == null)
|| (secret != null && scope != null && secret.getScope().equals(scope) && secret.isScopeValid());
// If we don't have a value, we can only restrict the scope further
if (value == null) {
if (isRaw()) {
throw new IllegalArgumentException("Unable to change scope from raw value with null value");
}
if (!encryptionUnchanged) {
var newSecret = secret.with(null, scope);
return new OptionalEncryptedValue<>(null, null, newSecret);
}
return this;
}
var newValueJson = JacksonMapper.getDefault().valueToTree(value);
if (value.equals(this.value) && newValueJson.equals(this.valueJson) && encryptionUnchanged) {
return this;
}
if (newValueJson.equals(this.valueJson) && encryptionUnchanged) {
return new OptionalEncryptedValue<>(newValueJson, value, secret);View on GitHub (pinned to d85ca821ba)
Solutions
- Only change scope on values that actually hold secret content: skip entries where value == null && isRaw().
- Provide a non-null value along with the scope change so the value can be encrypted for the new scope.
- If restricting scope of an empty value is intended, ensure the underlying secret is non-null so secret.with(null, scope) can run.
Example fix
// before
value.with(null, secret, newScope); // throws for raw null values
// after
if (value.getValue() != null || !value.isRaw()) {
value.with(null, secret, newScope);
} // else skip: nothing to re-scope Defensive patterns
Strategy: type-guard
Validate before calling
boolean canChangeScope = value.getValue() != null || !value.isRaw();
Type guard
boolean rescopeAllowed(OptionalEncryptedValue<?> v) { return v.getValue() != null || !v.isRaw(); } Try / catch
try {
value.with(null, secret, scope);
} catch (IllegalArgumentException e) {
// skip raw null values; nothing to re-scope
} Prevention
- Skip entries with null raw values in bulk scope updates.
- Save an actual secret value before trying to restrict its scope.
- Centralize scope changes in one helper that applies this guard.
When it happens
Trigger: Calling with(null, ...) on an OptionalEncryptedValue whose value is null and isRaw() is true, while passing a non-null scope (or a secret that changes the scope); typically reached via withUpdatedPrincipals() when the stored entry has no encrypted value yet.
Common situations: Programmatically updating access scope/principals on a freshly created store entry that has never been saved with an actual secret value; bulk scope-migration scripts touching placeholder/raw entries.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Encrypted value is null
- Secret is not accessible
- Principals must not be empty
- Name is empty
- Unable to parse or decrypt secret
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/c2558d8e8d88ad9d.
Report an issue: GitHub.