microsoft/aspire · error · InvalidOperationException
Expected Int32OrStringV1 but got
Error message
Expected Int32OrStringV1 but got {value?.GetType()} What it means
IntOrStringConverter.WriteYaml serializes Kubernetes Int32OrString values (quantities like ports or replicas that may be a number or a string). It throws InvalidOperationException when the value handed to the YAML serializer is not an Int32OrStringV1 instance. This is an internal invariant: the converter is registered for a specific type, so receiving anything else means the object graph or converter registration is wrong.
Solutions
- Ensure every value assigned to a member serialized with IntOrStringConverter is an Int32OrStringV1 instance (wrap ints/strings with the Int32OrStringV1 implicit conversions or constructor).
- Check that the converter is registered (IEventEmitters/IBetterYamlDotNet type resolution) only for typeof(Int32OrStringV1) and not applied to other types.
- If the value may legitimately be absent, ensure it is null-handled upstream rather than passed as a foreign type; a null here yields value?.GetType() == null in the message, pointing to an untyped null path.
Example fix
// before manifest.Spec.Ports[0].TargetPort = 8080; // plain int in a member typed object // after manifest.Spec.Ports[0].TargetPort = new Int32OrStringV1(8080);
Defensive patterns
Strategy: type-guard
Validate before calling
if (value is not Int32OrStringV1) throw new ArgumentException($"Expected Int32OrStringV1, got {value?.GetType().Name}"); Type guard
static bool IsValidIntOrString(object? v) => v is Int32OrStringV1;
Try / catch
try { serializer.Serialize(writer, value); } catch (InvalidOperationException ex) when (ex.Message.Contains("Int32OrStringV1")) { /* fix object graph type */ } Prevention
- Always assign Int32OrStringV1 (or use its implicit conversions) to fields serialized by this converter
- Keep converter registrations scoped to typeof(Int32OrStringV1)
- Add unit tests that serialize manifests end-to-end to catch type drift
When it happens
Trigger: Calling WriteYaml via YamlDotNet with the IntOrStringConverter registered for a type, but passing an object that is not Int32OrStringV1 (e.g. a raw int, string, or null) at src/Aspire.Hosting.Kubernetes/Yaml/IntOrStringConverter.cs:60.
Common situations: Custom code serializing a Kubernetes manifest graph where a property was assigned a plain int or string instead of Int32OrStringV1; manually invoking the converter against the wrong type; a custom resource type mimicking Int32OrStringV1 but using a different CLR type.
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 KubernetesManifestResource but got
- Command line args must be strings
- KubernetesManifestResource does not support YAML…
- The specified value is not an Int32.
- A ConfigureRadiusInfrastructure callback left container
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/aead0264bd0616ad.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Kubernetes/Yaml/IntOrStringConverter.cs:60
var value = scalar.Value;
parser.MoveNext();
return string.IsNullOrEmpty(value) ? null : new Int32OrStringV1(value);
}
/// <summary>
/// Writes the given object to the provided YAML emitter using the appropriate format.
/// </summary>
/// <param name="emitter">The emitter used to write the YAML output.</param>
/// <param name="value">The object to be serialized. Expected to be of type <see cref="Int32OrStringV1"/>.</param>
/// <param name="type">The type of the object being serialized.</param>
/// <param name="serializer">The serializer to be used for complex object serialization.</param>
/// <exception cref="InvalidOperationException">Thrown when the provided value is not of type <see cref="Int32OrStringV1"/>.</exception>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
if (value is not Int32OrStringV1 obj)
{
throw new InvalidOperationException($"Expected {nameof(Int32OrStringV1)} but got {value?.GetType()}");
}
if (obj.Number != null)
{
serializer(obj.Number);
}
else
{
var val = obj.Value ?? string.Empty;
serializer(val);
}
}
}
View on GitHub (pinned to 25830f84bd)