{"record":{"id":"063ea93afb37350b","repo":"elsa-workflows/elsa-core","slug":"elsa-platform-endpoint-is-required","errorCode":null,"errorMessage":"Elsa Platform endpoint is required.","messagePattern":"Elsa Platform endpoint is required\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Platform.Integration/Services/PlatformRuntimeCommandClient.cs","lineNumber":115,"sourceCode":"\n    private HttpRequestMessage CreateRequest(HttpMethod method, Uri uri)\n    {\n        var request = new HttpRequestMessage(method, uri);\n        if (!string.IsNullOrWhiteSpace(_options.EngineSecret))\n            request.Headers.TryAddWithoutValidation(EngineSecretHeaderName, _options.EngineSecret);\n        return request;\n    }\n\n    private async Task<HttpResponseMessage> SendJsonAsync<TRequest>(Uri uri, TRequest body, CancellationToken cancellationToken)\n    {\n        var request = CreateRequest(HttpMethod.Post, uri);\n        request.Content = JsonContent.Create(body, options: JsonOptions);\n        return await httpClient.SendAsync(request, cancellationToken);\n    }\n\n    private Uri BuildUri(string path)\n    {\n        var endpoint = _options.PlatformEndpoint ?? throw new InvalidOperationException(\"Elsa Platform endpoint is required.\");\n        if (Uri.TryCreate(path, UriKind.Absolute, out var absoluteUri))\n            return absoluteUri;\n\n        var relative = path.StartsWith(\"/api/\", StringComparison.OrdinalIgnoreCase)\n            ? path\n            : $\"/api/workspaces/{_options.WorkspaceId:D}{path}\";\n        return new Uri($\"{endpoint.AbsoluteUri.TrimEnd('/')}{relative}\");\n    }\n\n    private async Task CopyBoundedAsync(Stream source, Stream destination, CancellationToken cancellationToken)\n    {\n        var buffer = new byte[81920];\n        long total = 0;\n        while (true)\n        {\n            var read = await source.ReadAsync(buffer, cancellationToken);\n            if (read == 0)\n                return;","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Platform.Integration/Services/PlatformRuntimeCommandClient.cs#L97-L133","documentation":"BuildUri resolves request paths against _options.PlatformEndpoint. If PlatformEndpoint is null, it throws this InvalidOperationException because no request can be addressed. Absolute paths like artifact DownloadUrls bypass the endpoint, but the endpoint itself is always mandatory.","triggerScenarios":"Any PlatformRuntimeCommandClient call (PollAsync, complete/report, DownloadArtifactAsync) when _options.PlatformEndpoint was never assigned — typically because Validate() was never run or options were constructed in code without the endpoint.","commonSituations":"Registering the client manually without going through the feature's options pipeline that validates the endpoint; configuration key Elsa:PlatformIntegration:PlatformEndpoint missing in the environment; tests newing up options with only EngineId set.","solutions":["Set PlatformEndpoint to the absolute Platform base URL, e.g. https://platform.example.com.","Ensure options binding/validation runs at startup so this surfaces as a clear config error instead of a runtime failure.","Fix the missing configuration key in appsettings/environment variables for the deployment."],"exampleFix":"// before\nvar client = new PlatformRuntimeCommandClient(httpClient, new ElsaPlatformIntegrationOptions { EngineId = id });\n// after\nvar options = new ElsaPlatformIntegrationOptions { PlatformEndpoint = new Uri(\"https://platform.example.com\"), EngineId = id, WorkspaceId = wsId };\noptions.Validate();\nvar client = new PlatformRuntimeCommandClient(httpClient, options);","handlingStrategy":"validation","validationCode":"if (options.Enabled && string.IsNullOrWhiteSpace(options.PlatformEndpoint?.ToString()))\n    throw new InvalidOperationException(\"PlatformEndpoint must be configured before using the command client.\");","typeGuard":"bool HasEndpoint(ElsaPlatformIntegrationOptions o) => !string.IsNullOrWhiteSpace(o.PlatformEndpoint?.AbsoluteUri);","tryCatchPattern":"try { var commands = await client.PollAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"endpoint is required\"))\n{\n    logger.LogError(ex, \"PlatformEndpoint is not configured.\");\n}","preventionTips":["Always construct the client through Elsa's feature registration so options validation runs.","Set PlatformEndpoint via configuration and call ValidateOnStart.","Add an integration smoke test that performs a poll against configured options."],"tags":["configuration","url","platform-integration","api-client"],"backgroundTag":"missing-required-config-field","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}