{"record":{"id":"d7104317e50a12c8","repo":"microsoft/aspire","slug":"apitarget-is-required-when-apipath-is-specified","errorCode":null,"errorMessage":"apiTarget is required when apiPath is specified.","messagePattern":"apiTarget is required when apiPath is specified\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs","lineNumber":1291,"sourceCode":"            TargetEndpointName = targetEndpointName\n        };\n        return PublishAsStaticWebsiteCore(builder, apiPath, apiTarget, options);\n    }\n\n    [Experimental(\"ASPIREJAVASCRIPT001\", UrlFormat = \"https://aka.ms/aspire/diagnostics/{0}\")]\n    private static IResourceBuilder<TResource> PublishAsStaticWebsiteCore<TResource>(\n        IResourceBuilder<TResource> builder,\n        string? apiPath,\n        IResourceBuilder<IResourceWithServiceDiscovery>? apiTarget,\n        PublishAsStaticWebsiteOptions options)\n        where TResource : JavaScriptAppResource\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(options.OutputPath);\n\n        if (apiPath is not null && apiTarget is null)\n        {\n            throw new ArgumentException(\"apiTarget is required when apiPath is specified.\", nameof(apiTarget));\n        }\n\n        if (apiTarget is not null && apiPath is null)\n        {\n            throw new ArgumentException(\"apiPath is required when apiTarget is specified.\", nameof(apiPath));\n        }\n\n        if (apiPath is not null && apiTarget is not null)\n        {\n            if (!apiPath.StartsWith('/'))\n            {\n                throw new ArgumentException(\"The apiPath must start with '/'.\", nameof(apiPath));\n            }\n\n            apiPath = apiPath.TrimEnd('/');\n\n            if (apiPath.Length == 0)\n            {","sourceCodeStart":1273,"sourceCodeEnd":1309,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs#L1273-L1309","documentation":"Aspire's JavaScript hosting throws this when you specify an apiPath (the route prefix under which the API proxy is mounted) but omit the corresponding apiTarget (the resource the path proxies to). The two options are intentionally paired; the library cannot guess the target resource, so it fails fast at builder time.","triggerScenarios":"Calling the API-proxy configuration (e.g. WithApiProxy-style extension on AddViteApp/AddNpmApp results) with apiPath set but apiTarget null, e.g. .WithApiProxy(apiPath: \"/api\").","commonSituations":"Copy-pasting a sample and deleting the IResourceBuilder argument; the target resource builder variable being null at the call site; migrating from an API that previously inferred the target.","solutions":["Pass apiTarget together with apiPath, e.g. .WithApiProxy(apiPath: \"/api\", apiTarget: apiResourceBuilder).","If no API proxy is intended, remove apiPath entirely instead of passing it without a target.","Null-check the resource builder variable before the call so a missing target surfaces earlier with a clearer message."],"exampleFix":"// before\nbuilder.AddViteApp(\"frontend\", \"./frontend\")\n    .WithApiProxy(apiPath: \"/api\");\n// after\nbuilder.AddViteApp(\"frontend\", \"./frontend\")\n    .WithApiProxy(apiPath: \"/api\", apiTarget: apiProjectBuilder);","handlingStrategy":"validation","validationCode":"if (apiPath is not null && apiTarget is null)\n    throw new ArgumentException(\"apiTarget is required when apiPath is specified.\");","typeGuard":"bool HasCompleteProxyOptions(string? apiPath, IResourceBuilder<IResource>? apiTarget) =>\n    string.IsNullOrEmpty(apiPath) ? apiTarget is null : apiTarget is not null;","tryCatchPattern":"try { builder.WithApiProxy(apiPath, apiTarget); }\ncatch (ArgumentException ex) when (ex.ParamName == \"apiTarget\")\n{\n    // supply a default target or skip proxy configuration\n}","preventionTips":["Always pass apiPath and apiTarget together as a pair.","Null-check resource builders before referencing them in proxy options.","Wrap proxy configuration in a helper that enforces the pairing."],"tags":["aspire","javascript","argument-validation","api-proxy"],"backgroundTag":"missing-required-argument","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"}