{"record":{"id":"96fca72287dad974","repo":"microsoft/aspire","slug":"object-must-implement-ivalueprovider","errorCode":null,"errorMessage":"Object must implement IValueProvider","messagePattern":"Object must implement IValueProvider","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs","lineNumber":600,"sourceCode":"    /// <summary>\n    /// Appends a value provider to the expression using late binding.\n    /// The object must implement both <see cref=\"IValueProvider\"/> and <see cref=\"IManifestExpressionProvider\"/>,\n    /// or be an <see cref=\"IResourceBuilder{T}\"/> where T implements both interfaces.\n    /// </summary>\n    /// <ats-summary>Appends a value provider to the reference expression</ats-summary>\n    /// <param name=\"valueProvider\">An object that implements both interfaces, or an IResourceBuilder wrapping such an object.</param>\n    /// <ats-param name=\"valueProvider\">The value provider to append.</ats-param>\n    /// <param name=\"format\">Optional format specifier.</param>\n    /// <exception cref=\"ArgumentException\">Thrown if the object doesn't implement the required interfaces.</exception>\n    [AspireExport]\n    public void AppendValueProvider(object valueProvider, string? format = null)\n    {\n        // Unwrap IResourceBuilder<T> to get the underlying resource (covariant interface)\n        var unwrapped = valueProvider is IResourceBuilder<IResource> rb ? rb.Resource : valueProvider;\n\n        if (unwrapped is not IValueProvider vp)\n        {\n            throw new ArgumentException($\"Object must implement IValueProvider\", nameof(valueProvider));\n        }\n        if (unwrapped is not IManifestExpressionProvider mep)\n        {\n            throw new ArgumentException($\"Object must implement IManifestExpressionProvider\", nameof(valueProvider));\n        }\n\n        var index = _valueProviders.Count;\n        _builder.Append(CultureInfo.InvariantCulture, $\"{{{index}}}\");\n\n        _valueProviders.Add(vp);\n        _manifestExpressions.Add(mep.ValueExpression);\n        _stringFormats.Add(format);\n    }\n\n    /// <summary>\n    /// Builds the <see cref=\"ReferenceExpression\"/>.\n    /// </summary>\n    /// <ats-summary>Builds the reference expression</ats-summary>","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs#L582-L618","documentation":"ReferenceExpression.AppendValueProvider accepts an object that must implement both IValueProvider and IManifestExpressionProvider so its value can be resolved at run time and rendered as a manifest expression at publish time. Before checking either interface, the method unwraps IResourceBuilder<IResource> to the underlying resource via covariance. If after unwrapping the object still does not implement IValueProvider, an ArgumentException naming the 'valueProvider' parameter is thrown immediately.","triggerScenarios":"Calling ReferenceExpressionBuilder.AppendValueProvider (or an interpolated-string AppendFormatted overload that routes to it) with an object that implements neither IValueProvider nor IManifestExpressionProvider — e.g. a raw string, a plain POCO, an endpoint or connection-string object that isn't a value provider, or a custom type passed by mistake instead of the resource/parameter itself.","commonSituations":"Passing a builder (IResourceBuilder<T>) whose underlying resource class doesn't implement IValueProvider; passing strings or primitives where a parameter resource or ReferenceExpression is expected; hand-rolling a custom value provider but forgetting IValueProvider while only implementing IManifestExpressionProvider; upgrading Aspire versions where a type stopped implementing IValueProvider.","solutions":["Pass the actual resource or parameter (e.g. the IResourceBuilder<T>.Resource of a PostgresDatabaseResource, a parameter resource, or another ReferenceExpression) rather than an arbitrary object.","If passing an IResourceBuilder, it is accepted only when its Resource implements IValueProvider — check the resource type's interfaces or use a resource that supports expression generation.","For custom types, implement both IValueProvider (async GetValueAsync) and IManifestExpressionProvider (ManifestExpression) on the class.","If you just want a literal value, use CreateLiteral or append the string instead of AppendValueProvider."],"exampleFix":"// before\nvar expr = ReferenceExpression.Create($\"Host={someObject}\"); // someObject is a plain POCO\n\n// after\nvar expr = ReferenceExpression.Create($\"Host={builder.Resource}\"); // resource implements IValueProvider + IManifestExpressionProvider","handlingStrategy":"validation","validationCode":"if (value is not (IValueProvider and IManifestExpressionProvider) && value is not IResourceBuilder<IResource>)\n{\n    throw new ArgumentException(\"AppendValueProvider requires an object implementing IValueProvider and IManifestExpressionProvider.\", nameof(value));\n}","typeGuard":"static bool CanAppend(object? v) =>\n    (v is IResourceBuilder<IResource> rb ? rb.Resource : v) is IValueProvider and IManifestExpressionProvider;","tryCatchPattern":null,"preventionTips":["Only pass resources, parameters, or ReferenceExpressions that document support for expression generation.","For custom providers, always implement both IValueProvider and IManifestExpressionProvider together.","Check the resource type's implemented interfaces when switching Aspire versions."],"tags":["reference-expression","argument-validation","aspire-hosting"],"backgroundTag":"invalid-argument-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}