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

  1. Pass a properly constructed LoadUseLicenseForUserParams containing the target ContentUser
  2. Use the public useLicense-for-user API instead of invoking the callback directly
  3. Rebuild against matching WindowsBase versions so callback types line up
  4. 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

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


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)