microsoft/aspire · error · ArgumentException
A of type cannot be assigned to a BicepValue< >.
Error message
A {valueDescription} of type {_valueType.Name} cannot be assigned to a BicepValue<{targetType.Name}>. What it means
Before assigning a stored Bicep value to a BicepValue<T>, EnsureLiteralType compares the underlying types (unwrapping Nullable) of the source value and the target. A mismatch — e.g. assigning a string literal to BicepValue<int> — throws ArgumentException describing both the source ('literal' or 'value') and target types. This prevents Bicep output with wrong-typed values.
Solutions
- Convert the source literal to the target's underlying type before assignment (int.Parse, ToString, explicit cast).
- Check the BicepValue<T> generic argument at the target and match the stored literal type exactly.
- If the value comes from config, parse it to the correct type at the boundary instead of passing raw strings.
- Search the codebase for other assignments of the same property to keep types consistent after refactors.
Example fix
// before
proxy.AssignTo(bicepValue); // string "3" assigned to BicepValue<int>
// after
proxy.AssignTo(BicepValueFactory.Create(int.Parse("3"))); // matching int literal Defensive patterns
Strategy: validation
Validate before calling
// before assigning, check underlying types match
Type Unwrap(Type t) => Nullable.GetUnderlyingType(t) ?? t;
if (Unwrap(sourceType) != Unwrap(targetType)) { /* convert the literal first */ } Type guard
bool IsAssignableLiteral<T>(object value) => (Nullable.GetUnderlyingType(value.GetType()) ?? value.GetType()) == (Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T));
Try / catch
try { proxy.AssignTo(bicepValue); }
catch (ArgumentException ex) when (ex.Message.Contains("cannot be assigned to a BicepValue")) { /* parse/convert the literal to the target type and reassign */ } Prevention
- Parse config strings into the exact numeric/bool type of the Bicep property before assigning.
- Keep BicepValue<T> generic arguments and literal-producing code in sync during refactors.
- Centralize type conversion at the config boundary so raw strings never reach Bicep assignments.
When it happens
Trigger: Calling AssignTo (or chaining assignments) where the proxy's stored literal type differs from the BicepValue<T> target type: string to BicepValue<int>, int to BicepValue<string>, double to BicepValue<int>, or nullable-vs-non-null mismatches that unwrap to different underlying types.
Common situations: Config values read as strings assigned to numeric Bicep properties; numeric properties defined as int in app code but long/double in Bicep output; optional values (int?) assigned to non-optional proxies after underlying type drift; refactoring property types without updating assignment sites.
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
- Expected a string, integer, or
- Expected a literal 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/125c0cbc85ae997c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Provisioning/BicepValueProxy.cs:186
private void EnsureLiteralType(Type targetType)
{
if (_value.Kind != BicepValueKind.Literal && _valueType == typeof(object))
{
return;
}
if (targetType.IsAssignableFrom(_valueType))
{
return;
}
var sourceUnderlyingType = Nullable.GetUnderlyingType(_valueType) ?? _valueType;
var targetUnderlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;
if (sourceUnderlyingType != targetUnderlyingType)
{
var valueDescription = _value.Kind == BicepValueKind.Literal ? "literal" : "value";
throw new ArgumentException(
$"A {valueDescription} of type {_valueType.Name} cannot be assigned to a BicepValue<{targetType.Name}>.");
}
}
private IBicepValue GetAssignableValue()
{
// Azure Provisioning copies secure metadata from the source IBicepValue during assignment.
// Composing expressions creates a new SDK value that no longer carries that metadata, so
// expose the propagated state through an adapter without changing the emitted expression.
return IsSecure && !_value.IsSecure
? new SecureBicepValue(_value)
: _value;
}
private sealed class SecureBicepValue(IBicepValue inner) : IBicepValue
{
public BicepValueKind Kind => inner.Kind;
View on GitHub (pinned to 25830f84bd)