{"record":{"id":"0b38cc39acaa69d3","repo":"microsoft/aspire","slug":"service-ts-service-metadata-name-refers-to-endpoint-ts","errorCode":null,"errorMessage":"Service '{ts.Service!.Metadata.Name}' refers to endpoint '{ts.EndpointName}' that does not exist","messagePattern":"Service '(.+?)' refers to endpoint '(.+?)' that does not exist","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Dcp/DcpModelUtilities.cs","lineNumber":300,"sourceCode":"            var tunnelServices = allAppResources.Get().OfType<AppResource<Service>>().Select(r => (\n                Service: r.DcpResource,\n                ResourceName: r.DcpResource.Metadata.Annotations?.TryGetValue(CustomResource.ResourceNameAnnotation, out var resourceName) == true ? resourceName : null,\n                EndpointName: r.DcpResource.Metadata.Annotations?.TryGetValue(CustomResource.EndpointNameAnnotation, out var endpointName) == true ? endpointName : null,\n                TunnelInstanceName: r.DcpResource.Metadata.Annotations?.TryGetValue(CustomResource.ContainerTunnelInstanceName, out var tunnelInstanceName) == true ? tunnelInstanceName : null,\n                ContainerNetworkName: r.DcpResource.Metadata.Annotations?.TryGetValue(CustomResource.ContainerNetworkAnnotation, out var containerNetworkName) == true ? containerNetworkName : null\n            ))\n            .Where(ts =>\n                ts.Service is not null &&\n                string.Equals(ts.ResourceName, res.Name, StringComparisons.ResourceName) &&\n                !string.IsNullOrEmpty(ts.EndpointName) &&\n                !string.IsNullOrEmpty(ts.ContainerNetworkName)\n            );\n\n            foreach (var ts in tunnelServices)\n            {\n                if (!TryGetEndpoint(res, ts.EndpointName, out var endpoint))\n                {\n                    throw new InvalidDataException($\"Service '{ts.Service!.Metadata.Name}' refers to endpoint '{ts.EndpointName}' that does not exist\");\n                }\n\n                if (ts.Service?.HasCompleteAddress is not true)\n                {\n                    // This should never happen; if it does, we have a bug without a workaround for the user.\n                    throw new InvalidDataException($\"Container tunnel service {ts.Service?.Metadata.Name} should have valid address at this point\");\n                }\n\n                var serverSvc = allAppResources.Get().OfType<ServiceWithModelResource>().FirstOrDefault(swr =>\n                    string.Equals(swr.ModelResource.Name, ts.ResourceName, StringComparisons.ResourceName) &&\n                    string.Equals(swr.EndpointAnnotation.Name, endpoint.Name, StringComparisons.EndpointAnnotationName)\n                );\n                if (serverSvc is null)\n                {\n                    // Should never happen -- we should have created a Service for every endpoint exposed from a resource.\n                    throw new InvalidDataException($\"The '{endpoint.Name}' on resource '{ts.ResourceName}' should have an associated DCP Service resource already set up\");\n                }\n","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dcp/DcpModelUtilities.cs#L282-L318","documentation":"A container tunnel Service references an endpoint by name that cannot be found on the target resource. Tunnels are built from an endpoint of the model resource, so a missing endpoint means the tunnel annotation and the resource's endpoint set are out of sync — an internal consistency failure.","triggerScenarios":"AddContainerTunnelAllocatedEndpoints iterates tunnel services and calls TryGetEndpoint(res, ts.EndpointName); the resource has no endpoint annotation with that name (renamed or removed endpoint, ordering bug, stale tunnel metadata).","commonSituations":"Renaming an endpoint used by WithEndpoint on a resource consumed over the container network; removing an endpoint while tunnel/proxy wiring still references the old name; Aspire internal bugs in tunnel setup.","solutions":["Ensure the endpoint name referenced by the tunnel exists on the resource (check WithEndpoint names).","Rebuild/restart the AppHost so tunnel metadata regenerates after endpoint changes.","Clean stale artifacts (bin/obj, aspire cache) and update Aspire packages if it persists."],"exampleFix":"// before\n.WithEndpoint(\"https\", e => { ... }) // tunnel still references \"http\"\n// after\n.WithEndpoint(\"http\", e => { ... }) // name matches the endpoint the tunnel refers to","handlingStrategy":"validation","validationCode":"var tunnelEndpointNames = tunnelAnnotations.Select(t => t.EndpointName);\nvar resourceEndpoints = resource.Annotations.OfType<EndpointAnnotation>().Select(e => e.Name);\nvar missing = tunnelEndpointNames.Except(resourceEndpoints).ToList();\nif (missing.Count > 0) throw new InvalidOperationException($\"Tunnel references missing endpoints: {string.Join(',', missing)}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    app.Run();\n}\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"refers to endpoint\") && ex.Message.Contains(\"does not exist\"))\n{\n    // fix the endpoint name or rebuild to regenerate tunnel metadata\n}","preventionTips":["Treat endpoint names as contracts: rename them everywhere (including tunnel/proxy wiring) atomically.","Rebuild the AppHost (clean bin/obj) after endpoint renames.","Prefer constants/shared names for endpoints consumed across resources."],"tags":["aspire","dcp","tunnel","endpoint","containers"],"backgroundTag":"entity-not-found","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"}