{"record":{"id":"6d84f22d06c17fd2","repo":"Devolutions/UniGetUI","slug":"no-github-device-flow-is-pending-start-sign-in-fi","errorCode":null,"errorMessage":"No GitHub device flow is pending. Start sign-in first.","messagePattern":"No GitHub device flow is pending\\. Start sign-in first\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs","lineNumber":572,"sourceCode":"        return PackageBackupStartingKey + \" \" + deviceUser;\n    }\n\n    private static string ValidateBackupKey(string key)\n    {\n        if (string.IsNullOrWhiteSpace(key))\n        {\n            throw new InvalidOperationException(\"The backup key is required.\");\n        }\n\n        return key;\n    }\n\n    private static PendingGitHubDeviceFlow GetPendingGitHubDeviceFlow()\n    {\n        lock (GitHubAuthLock)\n        {\n            return _pendingGitHubDeviceFlow\n                ?? throw new InvalidOperationException(\n                    \"No GitHub device flow is pending. Start sign-in first.\"\n                );\n        }\n    }\n\n    private static void ClearPendingGitHubDeviceFlow()\n    {\n        lock (GitHubAuthLock)\n        {\n            _pendingGitHubDeviceFlow = null;\n        }\n    }\n}\n","sourceCodeStart":554,"sourceCodeEnd":586,"githubUrl":"https://github.com/Devolutions/UniGetUI/blob/9b1d7d0eab91620fc15c86b36676532095936ae3/src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs#L554-L586","documentation":"GetPendingGitHubDeviceFlow (called by CompleteGitHubDeviceFlowAsync) reads the static _pendingGitHubDeviceFlow field under a lock. If it is null — no device flow was ever started, or the previous one was cleared by expiry/sign-out — it throws InvalidOperationException. This is a precondition check: the completion step requires a prior initiation step.","triggerScenarios":"CompleteGitHubDeviceFlowAsync is called without a preceding successful StartGitHubDeviceFlowAsync. Or the pending flow was already cleared by: expiry (CompleteGitHubDeviceFlowAsync itself clears it on timeout), sign-out (SignOutGitHubAsync), or GetGitHubAuthInfoAsync's auto-clear on expiry. In a multi-daemon scenario, the pending flow lives in a different process's static field.","commonSituations":"The client calls complete before start. The flow expired and was auto-cleared by a status check. The user signed out between start and complete. A second process/session is involved (the static field is per-process). The app restarted, losing the in-memory pending flow.","solutions":["Always call StartGitHubDeviceFlowAsync before CompleteGitHubDeviceFlowAsync.","Check IpcGitHubAuthInfo.DeviceFlowPending (via GetStatusAsync) before attempting completion.","If the flow was cleared by expiry or restart, start a new one.","Ensure start and complete happen in the same process/session, since the pending flow is in-memory only."],"exampleFix":"// before: completing without starting\nawait IpcBackupApi.CompleteGitHubDeviceFlowAsync();\n// after: start first, then complete\nvar status = await IpcBackupApi.GetStatusAsync();\nif (!status.Auth.DeviceFlowPending)\n    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });\nawait IpcBackupApi.CompleteGitHubDeviceFlowAsync();","handlingStrategy":"validation","validationCode":"var status = await IpcBackupApi.GetStatusAsync();\nif (!status.Auth.DeviceFlowPending)\n    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });","typeGuard":"static bool HasPendingDeviceFlow(IpcGitHubAuthInfo auth) => auth.DeviceFlowPending;","tryCatchPattern":"try { await IpcBackupApi.CompleteGitHubDeviceFlowAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"No GitHub device flow is pending\"))\n{ await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true }); }","preventionTips":["Always start the device flow before completing it.","Check DeviceFlowPending before calling complete.","Keep start and complete in the same process — the pending state is in-memory."],"tags":["github","oauth","device-flow","authentication","state-management","ipc"],"backgroundTag":null,"analyzedSha":"9b1d7d0eab91620fc15c86b36676532095936ae3","analyzedAt":"2026-08-13T12:19:18.278Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}