{"record":{"id":"6edfeeedf46bc492","repo":"microsoft/autogen","slug":"repository-owner-login-is-null","errorCode":null,"errorMessage":"Repository owner login is null","messagePattern":"Repository owner login is null","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/samples/dev-team/DevTeam.Backend/Services/GithubWebHookProcessor.cs","lineNumber":30,"sourceCode":"using Octokit.Webhooks.Models;\n\nnamespace DevTeam.Backend.Services;\n\npublic sealed class GithubWebHookProcessor(ILogger<GithubWebHookProcessor> logger, Client client) : WebhookEventProcessor\n{\n    private readonly ILogger<GithubWebHookProcessor> _logger = logger;\n    private readonly Client _client = client;\n\n    protected override async Task ProcessIssuesWebhookAsync(WebhookHeaders headers, IssuesEvent issuesEvent, IssuesAction action)\n    {\n        try\n        {\n            ArgumentNullException.ThrowIfNull(headers, nameof(headers));\n            ArgumentNullException.ThrowIfNull(issuesEvent, nameof(issuesEvent));\n            ArgumentNullException.ThrowIfNull(action, nameof(action));\n\n            _logger.LogInformation(\"Processing issue event\");\n            var org = issuesEvent.Repository?.Owner.Login ?? throw new InvalidOperationException(\"Repository owner login is null\");\n            var repo = issuesEvent.Repository?.Name ?? throw new InvalidOperationException(\"Repository name is null\");\n            var issueNumber = issuesEvent.Issue?.Number ?? throw new InvalidOperationException(\"Issue number is null\");\n            var input = issuesEvent.Issue?.Body ?? string.Empty;\n            // Assumes the label follows the following convention: Skill.Function example: PM.Readme\n            // Also, we've introduced the Parent label, that ties the sub-issue with the parent issue\n            var labels = issuesEvent.Issue?.Labels\n                                    .Select(l => l.Name.Split('.'))\n                                    .Where(parts => parts.Length == 2)\n                                    .ToDictionary(parts => parts[0], parts => parts[1]);\n            if (labels == null || labels.Count == 0)\n            {\n                _logger.LogWarning(\"No labels found in issue. Skipping processing.\");\n                return;\n            }\n\n            long? parentNumber = labels.TryGetValue(\"Parent\", out var value) ? long.Parse(value) : null;\n            var skillName = labels.Keys.Where(k => k != \"Parent\").FirstOrDefault();\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/samples/dev-team/DevTeam.Backend/Services/GithubWebHookProcessor.cs#L12-L48","documentation":"Thrown by the dev-team sample's GitHub webhook processor when an IssuesEvent payload has no Repository.Owner.Login (null Owner, null Login, or null Repository). The webhook handler needs org + repo + issue number to dispatch work, so it fails fast rather than processing an event it cannot attribute to a repository.","triggerScenarios":"POSTing a test/minimal issues webhook payload (e.g. from a webhook debugging tool) that omits the repository object; receiving an event for a repository the integration has limited scope on; GitHub Enterprise Cloud payloads with different serialization; replaying captured payloads through a different deserialization path.","commonSituations":"Testing the webhook endpoint with curl and a hand-written minimal JSON body; webhook secret validation passing but payload trimmed; Octokit webhook model version drift where Repository moved; fork-related events where owner is an organization with missing login fields.","solutions":["Send a real captured GitHub issues webhook payload (GitHub repo Settings > Webhooks > Recent Deliverings > Redeliver) so repository.owner.login is present.","If testing locally, seed the payload with a complete repository.owner.login object instead of a minimal event.","Confirm the webhook is subscribed to issue events on the intended repo and the app installation has 'repository' read access.","If this fires in production, log the raw payload (issuesEvent.Repository?.FullName) and check whether GitHub changed the event shape in your Octokit webhook package version."],"exampleFix":"// before\nvar org = issuesEvent.Repository?.Owner.Login ?? throw new InvalidOperationException(\"Repository owner login is null\");\n\n// after (fail fast but log the payload shape for diagnosis)\nvar org = issuesEvent.Repository?.Owner?.Login\n    ?? throw new InvalidOperationException($\"Repository owner login is null (repo: {issuesEvent.Repository?.FullName ?? \"<null>\"}); webhook payload appears malformed or truncated.\");","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(issuesEvent.Repository?.Owner?.Login))\n{\n    _logger.LogWarning(\"Webhook payload missing repository.owner.login; skipping event {Action}.\", action);\n    return; // acknowledge 200 so GitHub doesn't retry a payload we can never process\n}","typeGuard":"static bool HasRepoContext(IssuesEvent e) => !string.IsNullOrWhiteSpace(e?.Repository?.Owner?.Login) && !string.IsNullOrWhiteSpace(e?.Repository?.Name) && e?.Issue?.Number is not null;","tryCatchPattern":"try { await ProcessIssuesWebhookAsync(headers, issuesEvent, action); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"Repository\")) { _logger.LogWarning(ex, \"Malformed webhook payload; acknowledging without processing.\"); /* return 200 to avoid redelivery storms */ }","preventionTips":["Validate repository/owner/name/issue-number presence before any processing and acknowledge-and-skip malformed deliveries instead of throwing (throwing makes GitHub retry the same bad payload).","Test webhook handlers with payloads captured from GitHub's 'Recent Deliveries' redelivery feature.","Log the event action and repository full name for every delivery to make null-field payloads diagnosable."],"tags":["github","webhook","octokit","dev-team-sample","payload-validation","csharp"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}