dotnet/wpf · error · ArgumentException
SR.CallbackParameterInvalid
Error message
SR.CallbackParameterInvalid
What it means
LoadUseLicenseForUser runs as a stream callback and expects its 'param' to be a LoadUseLicenseForUserParams instance carrying the desired user. Any other object type is rejected with ArgumentException (SR.CallbackParameterInvalid) naming 'param'. It is an internal callback contract violation.
Solutions
- Pass a properly constructed LoadUseLicenseForUserParams containing the target ContentUser
- Use the public useLicense-for-user API instead of invoking the callback directly
- Rebuild against matching WindowsBase versions so callback types line up
- In tests, mimic the exact callback signature and payload type
Example fix
// before transform.EnumerateStreams(callback, user); // wrong payload type // after var param = new LoadUseLicenseForUserParams(user); transform.EnumerateStreams(callback, param);
Defensive patterns
Strategy: type-guard
Validate before calling
if (param is not LoadUseLicenseForUserParams p) throw new ArgumentException("Callback param must be LoadUseLicenseForUserParams", nameof(param)); Type guard
bool IsValidCallbackParam(object param) => param is LoadUseLicenseForUserParams { User: not null }; Try / catch
try { callback(streamInfo, param, ref stop); } catch (ArgumentException ex) when (ex.ParamName == "param") { /* fix payload type */ } Prevention
- Always wrap the desired user in LoadUseLicenseForUserParams before invoking the callback
- Call public APIs instead of internal callbacks
- Keep test harnesses in sync with WindowsBase versions
When it happens
Trigger: Invoking the callback path with a param object that is not LoadUseLicenseForUserParams — typically only via incorrect internal/reflection-driven calls or a mismatched callback registration.
Common situations: Custom code (or tests) invoking the internal enumeration callback directly with wrong payload; version mismatch where the params wrapper type changed between assemblies.
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
- SR.CryptoProviderIsNotReady
- SR.OnlyPassportOrWindowsAuthenticatedUsersAreAllowed
- ArgumentOutOfRangeException(authentication)
- ArgumentOutOfRangeException(authenticationType)
- ArgumentOutOfRangeException(name)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/36bc63b3e455ffac.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptionTransform.cs:752
/// <param name="param">
/// Caller-supplied parameter to EnumUseLicenseStreams. In this case, it is a
/// LoadUseLicenseForUserParams object.
/// </param>
/// <param name="stop">
/// Set to true if the callback function wants to stop the enumeration. This callback
/// function never wants to stop the enumeration, so this parameter is not used.
/// </param>
private void
LoadUseLicenseForUser(
RightsManagementEncryptionTransform rmet,
StreamInfo si,
object param,
ref bool stop
)
{
if (param is not LoadUseLicenseForUserParams lulfup)
{
throw new ArgumentException(SR.CallbackParameterInvalid, nameof(param));
}
ContentUser userDesired = lulfup.User;
Debug.Assert(userDesired != null);
ContentUser userFromStream = null;
using (Stream stream = si.GetStream(FileMode.Open, FileAccess.Read))
{
using (BinaryReader utf8Reader = new BinaryReader(stream, Encoding.UTF8))
{
userFromStream = rmet.LoadUserFromStream(utf8Reader);
if (userFromStream.GenericEquals(userDesired))
{
lulfup.UseLicense = rmet.LoadUseLicenseFromStream(utf8Reader);
stop = true;
}
}View on GitHub (pinned to 81131a70a4)