{"record":{"id":"c6cc4c1c348d5a3c","repo":"microsoft/aspire","slug":"object-must-implement-imanifestexpressionprovider","errorCode":null,"errorMessage":"Object must implement IManifestExpressionProvider","messagePattern":"Object must implement IManifestExpressionProvider","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs","lineNumber":604,"sourceCode":"    /// </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>\n    [AspireExport]\n    public ReferenceExpression Build() =>\n        ReferenceExpression.Create(_builder.ToString(), [.. _valueProviders], [.. _manifestExpressions], [.. _stringFormats]);\n","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs#L586-L622","documentation":"AppendValueProvider requires its argument to implement both IValueProvider and IManifestExpressionProvider. This second check throws when the object (after unwrapping IResourceBuilder) implements IValueProvider but not IManifestExpressionProvider, so its value could be resolved at run time but has no stable expression for the published manifest. An ArgumentException naming 'valueProvider' is thrown.","triggerScenarios":"Calling AppendValueProvider (directly or via AppendFormatted in ReferenceExpression.Create interpolation) with a custom class that implements IValueProvider (or IValueProvider via IResourceBuilder) but omits IManifestExpressionProvider, so publishing manifests cannot render its placeholder.","commonSituations":"Hand-written custom resource value providers that implement only the runtime-resolution interface; types copied from older Aspire samples before IManifestExpressionProvider became required; passing an endpoint reference or custom annotation object that resolves values but doesn't participate in manifest generation.","solutions":["Add IManifestExpressionProvider to the custom type and return a stable '{resource}.value' style expression from ManifestExpression.","Pass a built-in resource type (parameter, connection string, endpoint-as-expression) that already implements both interfaces.","If only the literal/resolved value is needed, append the value as a string or use ReferenceExpression.Create with a supported provider instead.","Verify the object isn't an IResourceBuilder wrapping a resource that lacks IManifestExpressionProvider; unwrap and check the resource's interfaces."],"exampleFix":"// before\nclass MyValueSource : IValueProvider\n{\n    public ValueTask<string?> GetValueAsync(...) => ...; // no IManifestExpressionProvider\n}\n\n// after\nclass MyValueSource : IValueProvider, IManifestExpressionProvider\n{\n    public ValueTask<string?> GetValueAsync(...) => ...;\n    public ManifestExpression ManifestExpression => new(\"{myValueSource.value}\");\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static bool HasManifestSupport(object? v) =>\n    (v is IResourceBuilder<IResource> rb ? rb.Resource : v) is IManifestExpressionProvider;\n// require both: is IValueProvider and IManifestExpressionProvider","tryCatchPattern":"try\n{\n    builder.AppendValueProvider(provider);\n}\ncatch (ArgumentException ex) when (ex.ParamName == \"valueProvider\")\n{\n    // type lacks IManifestExpressionProvider; fall back or fix the provider type\n}","preventionTips":["Pair IValueProvider with IManifestExpressionProvider on every custom value source.","Prefer built-in resource types whose manifest support is guaranteed.","Run a publish/manifest generation step in tests to catch missing manifest support early."],"tags":["reference-expression","manifest","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"}