microsoft/aspire · error · ArgumentException
Expected a literal or .
Error message
Expected a {typeof(T).Name} literal or {nameof(BicepValueProxy)}. What it means
BicepValueProxy.Convert<T> unwraps a stored value to a concrete literal of type T. If the underlying value is not an instance of T (nor convertible via the checked path), the method throws ArgumentException stating it expected a T literal or a BicepValueProxy. This guards callers against silently mistyping Bicep values.
Solutions
- Call Convert with the generic type matching the literal originally stored (check the producing code).
- Parse/convert explicitly first: int.TryParse on strings before Convert<int>, or ToString() before Convert<string>.
- Use nullable-aware checks on the proxy's value type before converting.
- Centralize the expected type in one place so producer and consumer agree.
Example fix
// before var port = proxy.Convert<int>(); // stored as string "8080" // after var port = int.Parse(proxy.Convert<string>());
Defensive patterns
Strategy: type-guard
Validate before calling
if (proxy.ValueType == typeof(int)) { /* safe: proxy.Convert<int>() */ } Type guard
bool CanConvert<T>(BicepValueProxy p) where T : notnull => p.ValueType == typeof(T) || Nullable.GetUnderlyingType(p.ValueType) == typeof(T);
Try / catch
try { var v = proxy.Convert<int>(); }
catch (ArgumentException ex) when (ex.Message.Contains("literal or BicepValueProxy")) { /* read with the stored type and convert manually */ } Prevention
- Use the same generic type at the write site and the Convert read site.
- Convert explicitly (int.Parse/ToString) instead of relying on Convert<T> to coerce.
- Track Bicep value types in one definition to avoid write/read drift after refactors.
When it happens
Trigger: Calling Convert<T> (e.g. Convert<int>, Convert<string>) on a BicepValueProxy whose stored value was created from a different literal type — such as converting a string '8080' proxy to int, or an int proxy to string.
Common situations: Reading back a Bicep value with a mismatched generic argument; refactoring a value from string to int (or vice versa) in one place but not the read site; passing values parsed from config as strings into Convert<int>.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- A of type cannot be assigned to a BicepValue< >.
- Expected a string, integer, or
- An Azure principal parameter was not supplied a value…
- Azure resource ' ' is missing required output ' '. Ensure…
- AzureEnvironmentResource must be present in the application…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/ecd6718f06257359.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Provisioning/BicepValueProxy.cs:143
public static BicepValue<T> Convert<T>(object value)
{
ArgumentNullException.ThrowIfNull(value);
if (value is BicepValueProxy proxy)
{
proxy.EnsureLiteralType<T>();
var converted = new BicepValue<T>((T)default!);
proxy.AssignTo(converted);
return converted;
}
if (value is T literal)
{
return literal;
}
throw new ArgumentException($"Expected a {typeof(T).Name} literal or {nameof(BicepValueProxy)}.", nameof(value));
}
internal static BicepValueProxy CreateExpression(BicepExpression expression, bool isSecure)
{
ArgumentNullException.ThrowIfNull(expression);
return new(new BicepValue<object>(expression), typeof(object), isSecure);
}
internal BicepExpression ToBicepExpression()
{
return _value.ToBicepExpression();
}
internal BicepValue<object> ToObjectBicepValue()
{
return new(ToBicepExpression());
}View on GitHub (pinned to 25830f84bd)