{"record":{"id":"c2558d8e8d88ad9d","repo":"xpipe-io/xpipe","slug":"unable-to-change-scope-from-raw-value-with-null-va","errorCode":null,"errorMessage":"Unable to change scope from raw value with null value","messagePattern":"Unable to change scope from raw value with null value","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/xpipe/app/secret/OptionalEncryptedValue.java","lineNumber":89,"sourceCode":"\n    public OptionalEncryptedValue<T> withUpdatedPrincipals() {\n        return with(\n                value,\n                isEncrypted() ? DataStoreAccessScope.getTargetScope(getSecret().getScope()) : null);\n    }\n\n    public OptionalEncryptedValue<T> with(T value, DataStoreAccessScope scope) {\n        if (value == null && scope == null) {\n            return null;\n        }\n\n        var encryptionUnchanged = (secret == null && scope == null)\n                || (secret != null && scope != null && secret.getScope().equals(scope) && secret.isScopeValid());\n\n        // If we don't have a value, we can only restrict the scope further\n        if (value == null) {\n            if (isRaw()) {\n                throw new IllegalArgumentException(\"Unable to change scope from raw value with null value\");\n            }\n\n            if (!encryptionUnchanged) {\n                var newSecret = secret.with(null, scope);\n                return new OptionalEncryptedValue<>(null, null, newSecret);\n            }\n\n            return this;\n        }\n\n        var newValueJson = JacksonMapper.getDefault().valueToTree(value);\n\n        if (value.equals(this.value) && newValueJson.equals(this.valueJson) && encryptionUnchanged) {\n            return this;\n        }\n\n        if (newValueJson.equals(this.valueJson) && encryptionUnchanged) {\n            return new OptionalEncryptedValue<>(newValueJson, value, secret);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/secret/OptionalEncryptedValue.java#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvalue.with(null, secret, newScope); // throws for raw null values\n// after\nif (value.getValue() != null || !value.isRaw()) {\n    value.with(null, secret, newScope);\n} // else skip: nothing to re-scope","handlingStrategy":"type-guard","validationCode":"boolean canChangeScope = value.getValue() != null || !value.isRaw();","typeGuard":"boolean rescopeAllowed(OptionalEncryptedValue<?> v) { return v.getValue() != null || !v.isRaw(); }","tryCatchPattern":"try {\n    value.with(null, secret, scope);\n} catch (IllegalArgumentException e) {\n    // skip raw null values; nothing to re-scope\n}","preventionTips":["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."],"tags":["java","secrets","illegal-argument","null-value"],"backgroundTag":"invalid-argument-value","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}