{"record":{"id":"bce9fb54edd84eeb","repo":"elsa-workflows/elsa-core","slug":"elsa-platform-engine-secret-is-required-when-platform","errorCode":null,"errorMessage":"Elsa Platform engine secret is required when Platform integration is enabled.","messagePattern":"Elsa Platform engine secret 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":41,"sourceCode":"    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}\n","sourceCodeStart":23,"sourceCodeEnd":54,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Platform.Integration/Options/ElsaPlatformIntegrationOptions.cs#L23-L54","documentation":"Elsa's Platform integration options validator requires a non-empty EngineSecret when Platform integration is enabled. The secret authenticates this runtime engine to the Elsa Platform when polling for commands and downloading artifacts. Validate() is called during options binding/startup and throws InvalidOperationException on the first failing rule.","triggerScenarios":"Enabling Platform integration (Enabled = true) and calling ElsaPlatformIntegrationOptions.Validate() while EngineSecret is null, empty, or whitespace.","commonSituations":"Developers set endpoint, workspace ID, and engine ID from configuration but forget the engine secret; the secret is stored in a user-secrets/vault/keyvault binding that was not configured in the environment; a renamed configuration key (e.g. Elsa:Platform:EngineSecret) no longer binds.","solutions":["Set EngineSecret in ElsaPlatformIntegrationOptions (or bind it from configuration under the Elsa:PlatformIntegration section).","Provide the secret via environment variable or user secrets so it is available in the deployment environment.","If Platform integration is not intended, disable it (Enabled = false) so validation is skipped."],"exampleFix":"// before\noptions.Enabled = true;\noptions.EngineId = engineId;\n// after\noptions.Enabled = true;\noptions.EngineId = engineId;\noptions.EngineSecret = configuration[\"Elsa:PlatformIntegration:EngineSecret\"]!;","handlingStrategy":"validation","validationCode":"var secret = configuration[\"Elsa:PlatformIntegration:EngineSecret\"];\nif (string.IsNullOrWhiteSpace(secret))\n    throw new InvalidOperationException(\"Configure Elsa:PlatformIntegration:EngineSecret before enabling Platform integration.\");","typeGuard":null,"tryCatchPattern":"try { options.Validate(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"engine secret\"))\n{\n    logger.LogError(ex, \"Platform integration is enabled but EngineSecret is missing.\");\n}","preventionTips":["Store the engine secret in user secrets locally and a vault/keyvault reference in production.","Call options.Validate() at startup (OptionsBuilder.ValidateOnStart) so config errors fail fast.","Keep all Platform settings in one bound configuration section and document required keys."],"tags":["configuration","startup-validation","secrets","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"}