{"record":{"id":"509f3b7afc70ffac","repo":"elsa-workflows/elsa-core","slug":"a-metadata-value-is-required","errorCode":null,"errorMessage":"A metadata value is required.","messagePattern":"A metadata value is required\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs","lineNumber":36,"sourceCode":"    }\n\n    /// <inheritdoc />\n    public IReadOnlyDictionary<string, string> GetMetadata()\n    {\n        var metadata = CurrentFrame.Value?.Metadata;\n        return metadata == null || metadata.Count == 0\n            ? Empty\n            : new Dictionary<string, string>(metadata, StringComparer.OrdinalIgnoreCase);\n    }\n\n    /// <inheritdoc />\n    public IDisposable PushMetadata(string key, string value)\n    {\n        if (string.IsNullOrWhiteSpace(key))\n            throw new ArgumentException(\"A metadata key is required.\", nameof(key));\n\n        if (string.IsNullOrWhiteSpace(value))\n            throw new ArgumentException(\"A metadata value is required.\", nameof(value));\n\n        var previous = CurrentFrame.Value;\n        var metadata = previous?.Metadata != null\n            ? new Dictionary<string, string>(previous.Metadata, StringComparer.OrdinalIgnoreCase)\n            : new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n\n        metadata[key] = value;\n        CurrentFrame.Value = new(metadata);\n        return new MetadataScope(previous);\n    }\n\n    /// <inheritdoc />\n    public IDisposable PushWorkflowInstanceId(string workflowInstanceId) =>\n        PushMetadata(ConsoleLogMetadataKeys.WorkflowInstanceId, workflowInstanceId);\n\n    private sealed record MetadataFrame(IReadOnlyDictionary<string, string> Metadata);\n\n    private sealed class MetadataScope(MetadataFrame? previous) : IDisposable","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs#L18-L54","documentation":"ConsoleLogContextAccessor.PushMetadata validates both arguments before pushing an ambient metadata frame via AsyncLocal. It throws ArgumentException when the key or the value is null, empty, or whitespace. The accessor uses an OrdinalIgnoreCase metadata dictionary, so keys are case-insensitive but never optional.","triggerScenarios":"Calling PushMetadata(key, \"\") or PushMetadata(key, \"   \"); also via wrapper methods like PushWorkflowInstanceId when a null/empty workflow instance id is passed in.","commonSituations":"Reading a workflow instance id from a nullable context property or configuration value that has not been populated yet, then pushing it unconditionally without a null/empty check.","solutions":["Check string.IsNullOrWhiteSpace(value) at the call site and skip the PushMetadata call when it is empty.","Coalesce the value to a placeholder (e.g. value ?? \"unknown\") if an entry must always be pushed.","Fix the upstream source (workflow context, config, DI registration) so the instance id is populated before logging metadata."],"exampleFix":"// before\nusing var _ = accessor.PushWorkflowInstanceId(instanceId);\n\n// after\nif (!string.IsNullOrWhiteSpace(instanceId))\n    using var _ = accessor.PushWorkflowInstanceId(instanceId);","handlingStrategy":"validation","validationCode":"if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value))\n    accessor.PushMetadata(key, value);","typeGuard":null,"tryCatchPattern":"try { accessor.PushMetadata(key, value); }\ncatch (ArgumentException ex) { logger.LogWarning(ex, \"Skipped metadata push: {Message}\", ex.Message); }","preventionTips":["Wrap PushMetadata in a helper that no-ops on null/empty values.","Never push metadata derived from nullable context or config values without checking them first."],"tags":["argument-validation","logging","metadata"],"backgroundTag":"empty-required-field","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}