Skip to main content

How to Resolve Error "CS0655: Not a valid named attribute argument because it is not a valid attribute parameter type" in C#

The Compiler Error CS0655 is a restriction error regarding Attribute usage. The message reads: " 'Name' is not a valid named attribute argument because it is not a valid attribute parameter type".

In C#, attributes are metadata serialized into the compiled binary (assembly). Because they must be "baked in" at compile-time, the Common Language Runtime (CLR) restricts the types of data you can pass to an attribute. You can only pass values that are compile-time constants and are supported by the attribute serialization format. This error occurs when you define a property in an attribute class using an unsupported type (like decimal, DateTime, or Guid) and try to assign a value to it using a named argument.

This guide lists the allowed types and demonstrates workarounds for unsupported types.

Understanding Valid Attribute Types

The CLR restricts attribute parameters (both constructor arguments and named properties) to a specific subset of types.

Allowed Types:

  • Primitives: bool, byte, char, short, int, long, float, double (and their unsigned counterparts).
  • Strings: string.
  • Types: System.Type.
  • Enums: Any public enum.
  • Arrays: Single-dimensional arrays of the types above.
  • Object: Provided the actual value assigned is one of the types above.

NOT Allowed (Common Triggers for CS0655):

  • decimal (Not a primitive in the CLR).
  • DateTime.
  • Guid.
  • Any custom Class or Struct.

Scenario 1: The decimal Restriction

This is the most common cause. While decimal is a built-in C# type, it is not a primitive type in the CLR metadata format. Therefore, you cannot use it as a named argument in an attribute.

Example of error

Defining an attribute with a decimal property and trying to set it.

using System;

public class ProductAttribute : Attribute
{
// It is legal to define this property inside the class...
public decimal Price { get; set; }
}

// ⛔️ Error CS0655: 'Price' is not a valid named attribute argument
// because it is not a valid attribute parameter type.
[Product(Price = 19.99m)]
public class Laptop
{
}

Solution: Use Double or String

You must change the underlying type of the property in the attribute class. Use double if floating-point precision is acceptable for metadata, or string if exact precision is required (and parse it later).

using System;

public class ProductAttribute : Attribute
{
// ✅ Correct: Change the backing store to a supported type (double)
public double Price { get; set; }
}

[Product(Price = 19.99)]
public class Laptop
{
}
note

If you stick with double, remember that 19.99 might be stored as 19.98999.... If exact financial precision is needed in the metadata, store it as a string ("19.99") and use decimal.Parse() in your reflection code.

Scenario 2: Using DateTime or Guid

Dates and Guids are complex structures that cannot be serialized into the attribute metadata format directly.

Example of error

using System;

public class HistoryAttribute : Attribute
{
public DateTime ModifiedDate { get; set; }
public Guid UniqueId { get; set; }
}

// ⛔️ Error CS0655: Neither DateTime nor Guid can be passed as named arguments.
[History(ModifiedDate = DateTime.Now, UniqueId = new Guid("..."))]
public class User
{
}

Solution: Pass Strings

Convert the values to strings.

using System;

public class HistoryAttribute : Attribute
{
// Storage strings
public string DateString { get; set; }
public string GuidString { get; set; }

// Helper properties to parse them (Logic resides here)
public DateTime GetDate() => DateTime.Parse(DateString);
public Guid GetId() => Guid.Parse(GuidString);
}

// ✅ Correct: Pass strings that can be parsed later.
[History(DateString = "2023-10-01", GuidString = "d22c100c-9c9b-4395-9272-c5d956555555")]
public class User
{
}

Conclusion

CS0655 is a limitation of the .NET metadata format.

  1. Check the Type: Are you trying to assign a decimal, DateTime, Guid, or custom Class to an attribute property?
  2. Use Primitives: Switch to int, double, bool, or string.
  3. Parse Later: If you need a complex type, store it as a string in the attribute and parse it back into the complex type when you read the attribute via Reflection.