{"record":{"id":"fabc6c27a0ec8e4f","repo":"microsoft/aspire","slug":"the-apipath-must-not-be-it-would-match-all-requests-and-make","errorCode":null,"errorMessage":"The apiPath must not be '/' — it would match all requests and make the static site unreachable.","messagePattern":"The apiPath must not be '/' — it would match all requests and make the static site unreachable\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs","lineNumber":1310,"sourceCode":"        }\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            {\n                throw new ArgumentException(\"The apiPath must not be '/' — it would match all requests and make the static site unreachable.\", nameof(apiPath));\n            }\n\n            ValidateApiPath(apiPath);\n            builder.WithReference(apiTarget);\n        }\n\n        if (!builder.ApplicationBuilder.ExecutionContext.IsPublishMode)\n        {\n            return builder;\n        }\n\n        // YARP listens on port 5000 by default in the base image, so configure an endpoint for that port\n        // and set ASPNETCORE_URLS to ensure Kestrel listens on the correct port as well for static file serving and API reverse-proxy to work correctly.\n        builder.WithEndpoint(\"http\", e => e.TargetPort = 5000, createIfNotExists: true);\n\n        var annotation = new JavaScriptPublishModeAnnotation(JavaScriptPublishMode.StaticWebsite)\n        {\n            OutputPath = options.OutputPath,","sourceCodeStart":1292,"sourceCodeEnd":1328,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs#L1292-L1328","documentation":"An apiPath of '/' would make the proxy intercept every request to the static site, so the SPA assets would never be served. Aspire rejects it after normalizing (trailing slashes are trimmed, so '///' also collapses to empty) and requires a real sub-path prefix.","triggerScenarios":"Calling the API-proxy extension with apiPath: \"/\" (or a value that becomes empty after TrimEnd('/')), with a valid apiTarget.","commonSituations":"Attempting to proxy all traffic to a backend; a configurable prefix string that defaults to \"/\"; misunderstanding that trimming turns \"/api/\" into \"/api\" (fine) but \"/\" into empty (error).","solutions":["Use a distinct sub-path such as \"/api\" instead of \"/\".","If everything must go to the backend, do not use the static-site proxy; point the resource at the backend directly or reverse-proxy at the infrastructure layer.","Guard configurable values: if (string.IsNullOrEmpty(path.Trim('/'))) require a non-root default."],"exampleFix":"// before\n.WithApiProxy(apiPath: \"/\", apiTarget: apiBuilder);\n// after\n.WithApiProxy(apiPath: \"/api\", apiTarget: apiBuilder);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(apiPath?.TrimEnd('/')))\n    throw new ArgumentException(\"apiPath must be a non-root sub-path, not '/'.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never configure the proxy root for a static site; always use a named sub-path like /api.","Validate configuration-driven prefixes with path.Trim('/') before use.","Remember trailing slashes are trimmed; test edge values like \"/api/\" and \"/\"."],"tags":["aspire","javascript","argument-validation","routing"],"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"}