peass-ng/PEASS-ng · error · ArgumentException
Can not serialize non-public type {0}.
Error message
Can not serialize non-public type {0}. What it means
ObjectMemberAccessor's private constructor builds a reflection-based accessor for a type. The check that rejects non-public types is commented out in this vendored copy, so under the original logic ArgumentException('Can not serialize non-public type {0}.') fires when the constructor is given an internal/private type for YAML serialization. The snippet shown is the source region where that guard would execute.
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/YamlSerializer/ObjectMemberAccessor.cs:46
/// 指定した型へのアクセス方法を表すインスタンスを返す
/// キャッシュに存在すればそれを返す
/// キャッシュに存在しなければ新しく作って返す
/// 作った物はキャッシュされる
/// </summary>
/// <param name="type">クラスまたは構造体を表す型情報</param>
/// <returns></returns>
public static ObjectMemberAccessor FindFor(Type type)
{
if ( !MemberAccessors.ContainsKey(type) )
MemberAccessors[type] = new ObjectMemberAccessor(type);
return MemberAccessors[type];
}
private ObjectMemberAccessor(Type type)
{
/*
if ( !TypeUtils.IsPublic(type) )
throw new ArgumentException(
"Can not serialize non-public type {0}.".DoFormat(type.FullName));
*/
// public properties
foreach ( var p in type.GetProperties(
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.GetProperty) ) {
var prop = p; // create closures with this local variable
// not readable or parameters required to access the property
if ( !prop.CanRead || prop.GetGetMethod(false) == null || prop.GetIndexParameters().Count() != 0 )
continue;
Func<object, object> get = obj => prop.GetValue(obj, EmptyObjectArray);
Action<object, object> set = null;
if ( prop.CanWrite && prop.GetSetMethod(false) != null )
set = (obj, value) => prop.SetValue(obj, value, EmptyObjectArray);
RegisterMember(type, prop, prop.PropertyType, get, set);
}View on GitHub (pinned to 53fb989abc)
Solutions
- Make the type public (or the relevant members public) so the serializer can reflect it.
- Use [YamlSerializable]-compatible public DTOs as an intermediary and map from internal types.
- If you control the vendored serializer, note the guard is commented out — non-public types now pass through but may fail later on member access.
- Add InternalsVisibleTo if the serializer runs in a friend assembly context.
Example fix
// before
internal class Config { public string Name; } // serializer may reject
// after
public class Config { public string Name; } Defensive patterns
Strategy: type-guard
Validate before calling
if (type != null && !type.IsPublic && !type.IsNestedPublic) throw new ArgumentException(type.FullName + " must be public for YAML serialization");
Type guard
static bool IsYamlSerializable(Type t) => t.IsPublic || t.IsNestedPublic;
Try / catch
try { serializer.Serialize(writer, obj); } catch (ArgumentException ex) when (ex.Message.Contains("non-public")) { mapToPublicDtoAndRetry(); } Prevention
- Keep serialized DTO types public
- Add a reflection smoke test that accesses all serializable types
- Avoid serializing internal domain types directly
When it happens
Trigger: Constructing an ObjectMemberAccessor (via the YAML serializer) for a type not visible to the serializer — internal/private classes, or public types in unsigned assemblies without InternalsVisibleTo being reflected over.
Common situations: Serializing internal config/model classes; types marked internal in libraries; generic types instantiated with internal type arguments.
Related errors
- {0} {1} is not writeable by {2}.
- {0} {1} of {2} is not an array. Can not be serialized as bin
- drivePath
- Resources.InvalidDriveLetterArgument
- driveName
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/1aa37df415775da8.
Report an issue: GitHub.