{"record":{"id":"046ac79cfa949640","repo":"elsa-workflows/elsa-core","slug":"elsa-platform-endpoint-is-required-when-platform-integration","errorCode":null,"errorMessage":"Elsa Platform endpoint is required when Platform integration is enabled.","messagePattern":"Elsa Platform endpoint is required when Platform integration is enabled\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Platform.Integration/Options/ElsaPlatformIntegrationOptions.cs","lineNumber":35,"sourceCode":"    public string WorkerId { get; set; } = $\"{Environment.MachineName}:{Environment.ProcessId}\";\n\n    public TimeSpan PollInterval { get; set; } = TimeSpan.FromSeconds(5);\n\n    public TimeSpan ClaimLeaseDuration { get; set; } = TimeSpan.FromMinutes(5);\n\n    public long MaxArtifactBytes { get; set; } = 4 * 1024 * 1024;\n\n    public string ShellOverlayPath { get; set; } = \"platform-shell-overrides.json\";\n\n    public IReadOnlyList<string> Capabilities { get; set; } = [\"loom.recipe.apply\"];\n\n    public void Validate()\n    {\n        if (!Enabled)\n            return;\n\n        if (PlatformEndpoint is null)\n            throw new InvalidOperationException(\"Elsa Platform endpoint is required when Platform integration is enabled.\");\n        if (WorkspaceId == Guid.Empty)\n            throw new InvalidOperationException(\"Elsa Platform workspace ID is required when Platform integration is enabled.\");\n        if (EngineId == Guid.Empty)\n            throw new InvalidOperationException(\"Elsa Platform engine ID is required when Platform integration is enabled.\");\n        if (string.IsNullOrWhiteSpace(EngineSecret))\n            throw new InvalidOperationException(\"Elsa Platform engine secret is required when Platform integration is enabled.\");\n        if (string.IsNullOrWhiteSpace(WorkerId))\n            throw new InvalidOperationException(\"Elsa Platform worker ID is required when Platform integration is enabled.\");\n        if (PollInterval <= TimeSpan.Zero)\n            throw new InvalidOperationException(\"Elsa Platform poll interval must be positive.\");\n        if (ClaimLeaseDuration < TimeSpan.FromSeconds(1) || ClaimLeaseDuration.TotalSeconds > int.MaxValue)\n            throw new InvalidOperationException(\"Elsa Platform claim lease duration must be between 1 second and the maximum supported Platform lease.\");\n        if (MaxArtifactBytes <= 0 || MaxArtifactBytes > Array.MaxLength)\n            throw new InvalidOperationException(\"Elsa Platform maximum artifact size must be between 1 byte and the maximum runtime buffer size.\");\n        if (string.IsNullOrWhiteSpace(ShellOverlayPath))\n            throw new InvalidOperationException(\"Elsa Platform shell overlay path is required when Platform integration is enabled.\");\n    }\n}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Platform.Integration/Options/ElsaPlatformIntegrationOptions.cs#L17-L53","documentation":"ElsaPlatformIntegrationOptions.Validate enforces that when Enabled is true, a PlatformEndpoint must be configured. Without it the Platform integration client has no server URL to connect to, so the option object considers the configuration invalid and throws immediately.","triggerScenarios":"Calling Validate() (typically at feature startup) with Enabled = true and PlatformEndpoint left null — e.g. enabling the integration flag without setting the endpoint in appsettings or via the options builder.","commonSituations":"Setting Enabled=true but forgetting the endpoint URL; endpoint bound from an env var that is unset; config section typo so binding never populates PlatformEndpoint.","solutions":["Set options.PlatformEndpoint to a valid absolute URI of the Elsa Platform server.","Provide the endpoint via configuration (appsettings.json / environment variable) before the feature starts.","Set Enabled = false if you do not intend to use Platform integration."],"exampleFix":"// before\nvar options = new ElsaPlatformIntegrationOptions { Enabled = true, WorkspaceId = guid, EngineId = guid, EngineSecret = \"s\", WorkerId = \"w\" };\noptions.Validate();\n// after\nvar options = new ElsaPlatformIntegrationOptions { Enabled = true, PlatformEndpoint = new Uri(\"https://platform.example.com\"), WorkspaceId = guid, EngineId = guid, EngineSecret = \"s\", WorkerId = \"w\" };\noptions.Validate();","handlingStrategy":"validation","validationCode":"if (options.Enabled && options.PlatformEndpoint is null)\n    throw new InvalidOperationException(\"PlatformEndpoint must be set when Platform integration is enabled.\");","typeGuard":"bool IsValid(ElsaPlatformIntegrationOptions o) => !o.Enabled || o.PlatformEndpoint is not null;","tryCatchPattern":"try { options.Validate(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"endpoint is required\")) { /* surface startup config error */ }","preventionTips":["Validate options at startup via IValidateOptions so failures surface early.","Bind the endpoint from a required config key with fail-fast semantics.","Document the required keys in the options class."],"tags":["configuration","options-validation","platform-integration"],"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"}