How to Fix Epic Online Services Unreal Blueprint Login Failures and Achievement Errors
In a nutshell
Debug epic online services unreal blueprint login issues and fix broken achievement syncs with this technical guide for Unreal Engine developers.
You compile a shipping build of your Unreal Engine game, launch it from the Epic Games Launcher, and click your custom login button. Nothing happens, or the game client freezes, and your logs populate with cryptic authentication failure notices. Even worse, your achievement unlock node runs without throwing any visible errors, yet the player's profile in the Epic Games Store overlay remains completely empty. These errors are incredibly common when integrating storefront APIs. Fortunately, they can be resolved by correcting your asynchronous execution flow and understanding how the subsystem maps user identities.
Understanding the EOS Authentication Pipeline: EAID vs. PUID
Integrating Epic Online Services (EOS) via Unreal Engine's Online Subsystem (OSS) requires navigating a two-tier identity system. The Epic Account ID (EAID) is managed by the Auth Interface. It validates who the user is on the storefront level, enabling features like the social overlay, friends lists, and Epic Games Store library checks.
Conversely, the Product User ID (PUID) is managed by the Connect Interface. The PUID is a game-specific identifier that links the user to backend game services. These services include matchmaking, stats, cloud saves, and achievements.
Why EAID and PUID Mismatches Break Achievements
A common failure mode occurs when developers successfully authenticate with the Auth Interface (generating an EAID) but the subsystem fails to log in to the Connect Interface. Because achievements are managed by the Connect Interface using PUIDs, writing achievement progress without a resolved PUID fails with an EOS_InvalidUser error.
In games that launch without a storefront wrapper, users typically log in with credentials that are checked against a centralized user table. In a modern storefront ecosystem like Epic Games Store, identity is federated. When your game launches, it receives a cryptographic ticket from the launcher. The game then passes this ticket to the storefront's authentication servers. The SDK returns an Epic Account ID, which acts as the user's passport across all games on the platform.
However, to maintain privacy and cross-play security, Epic does not allow game-specific features like achievements to read the Epic Account ID directly. Instead, the game must initialize the Connect Interface, which performs a secondary exchange to retrieve a Product User ID. This separation ensures that if your game is hacked, the players' global Epic Account credentials are not compromised. Without the PUID, your game is effectively operating in an unauthenticated guest state, blocking access to EGS features. If your credentials config or client policy lacks the correct permissions in the Epic Developer Portal, this linkage fails. The identity interface reports a successful login because the Epic account is valid, but the game services layer cannot write achievement data because no PUID was ever linked.
The Anatomy of a Broken Blueprint Login Sequence
Many developers run into login issues by chaining their Blueprint execution pins linearly. Dragging the execution pin from a Login node directly into a Query Achievements or Write Achievement Progress node will always fail.
Authentication requests must travel to the Epic backend, making them asynchronous. The engine continues executing the Blueprint graph on the very next frame, long before the Epic servers return user credentials. At this stage, the player's Unique Net ID remains null.
The "Missing Node" Mismatch: Race Conditions in Async Execution
If you call achievement nodes immediately after the login node, the subsystem throws a silent error because the cached user state is empty. The correct workflow requires binding custom events to the subsystem's asynchronous delegates.
Furthermore, developers often miss the crucial step of caching achievements before writing to them. You cannot modify an achievement's progress without first querying the server for the current schema. Calling Write Achievements without a prior Query Achievements call results in a silent failure or an EOS_InvalidUser error in your console log because the local cached achievement map size is 0.
The Correct Asynchronous Blueprint Flow
To resolve this, you must separate the login trigger from the achievement update. First, call the login node and specify the correct authentication credentials.
Second, bind an event to the On Login Complete delegate of the identity interface. Once this event fires and returns a success status, fetch the user's Unique Net ID.
Third, pass this ID into the Query Achievements node. Finally, bind an event to the On Query Achievements Complete delegate, and only call Write Achievement Progress within that callback.
Implementing a Robust EOS Login & Achievement Controller in C++
To handle these asynchronous operations cleanly, implementing the authentication loop in C++ is highly recommended. It provides direct access to the IOnlineSubsystem and its interfaces.
Below is a complete, production-ready C++ implementation of a login and achievement handler:
#include "OnlineSubsystem.h"
#include "Interfaces/OnlineIdentityInterface.h"
#include "Interfaces/OnlineAchievementsInterface.h"
#include "OnlineSubsystemUtils.h"
void UEOSLoginHandler::LoginToEpicGames(APlayerController* PlayerController)
{
if (!PlayerController) return;
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
if (!Subsystem)
{
UE_LOG(LogTemp, Warning, TEXT("EOS Subsystem not found. Make sure the plugin is enabled."));
return;
}
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
if (Identity.IsValid())
{
FOnlineAccountCredentials Credentials;
Credentials.Type = TEXT("ExchangeCode");
Credentials.Id = TEXT("");
Credentials.Token = TEXT(""); // The launcher passes this via command line arguments
Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &UEOSLoginHandler::OnLoginComplete));
Identity->Login(0, Credentials);
}
}
void UEOSLoginHandler::OnLoginComplete(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
if (!bWasSuccessful)
{
UE_LOG(LogTemp, Error, TEXT("Epic Online Services Login Failed. Error: %s"), *Error);
return;
}
UE_LOG(LogTemp, Log, TEXT("EOS Login Successful. ID resolved: %s"), *UserId.ToString());
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
IOnlineAchievementsPtr Achievements = Subsystem->GetAchievementsInterface();
if (Achievements.IsValid())
{
Achievements->QueryAchievements(UserId, FOnQueryAchievementsCompleteDelegate::CreateUObject(this, &UEOSLoginHandler::OnQueryAchievementsComplete));
}
}
void UEOSLoginHandler::OnQueryAchievementsComplete(const FUniqueNetId& PlayerId, bool bWasSuccessful)
{
if (!bWasSuccessful)
{
UE_LOG(LogTemp, Warning, TEXT("Failed to query achievements from Epic Developer Portal."));
return;
}
UE_LOG(LogTemp, Log, TEXT("Achievements queried successfully. Now writing progress."));
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
IOnlineAchievementsPtr Achievements = Subsystem->GetAchievementsInterface();
if (Achievements.IsValid())
{
FOnlineAchievementsWriteRef WriteObject = MakeShared<FOnlineAchievementsWrite>();
WriteObject->SetFloatStat(TEXT("ACH_FIRST_BLOOD"), 100.0f);
Achievements->WriteAchievements(PlayerId, WriteObject, FOnAchievementsWrittenDelegate::CreateUObject(this, &UEOSLoginHandler::OnAchievementsWritten));
}
}
void UEOSLoginHandler::OnAchievementsWritten(const FUniqueNetId& PlayerId, bool bWasSuccessful)
{
if (bWasSuccessful)
{
UE_LOG(LogTemp, Log, TEXT("Achievement successfully unlocked on Epic Games Store!"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to write achievement progress. Check sandbox mappings."));
}
}
This controller utilizes sequential callbacks. It ensures that the achievement interface is only accessed once the identity interface has successfully resolved both the Epic Account ID and the Product User ID.
Configuring your DefaultEngine.ini File for EOS
Blueprint login nodes will fail to initialize if the configurations in your Config/DefaultEngine.ini file are incorrect. The Online Subsystem EOS plugin requires specific parameters to bind to your game client.
Use the following configuration template to ensure your subsystem initializes properly:
[OnlineSubsystem]
DefaultPlatformService=EOS
[OnlineSubsystemEOS]
bEnabled=true
bUseEpicConnect=true
ProductId=your_product_id_here
SandboxId=your_sandbox_id_here
DeploymentId=your_deployment_id_here
ClientId=your_client_id_here
ClientSecret=your_client_secret_here
[OnlineSubsystemEOS.Auth]
bUseEpicAccount=true
The configuration of your DefaultEngine.ini file acts as the bridge between your compiled game binaries and the Epic Developer Portal. The parameters under [OnlineSubsystemEOS] must match your product settings exactly.
A common source of confusion is the difference between client credentials and sandbox IDs. The Client ID and Client Secret represent the credentials of your game client, allowing it to communicate with the EOS backend. The Sandbox ID represents the specific environment (such as Development, Staging, or Live) that your client is accessing.
If your game client attempts to authenticate with a Sandbox ID that does not match the Client Credentials policy, the authentication request will be rejected. Additionally, the bUseEpicConnect flag must be set to true to ensure the Online Subsystem handles the EAID-to-PUID mapping automatically behind the scenes.
Managing Overlay Focus Mismatches and Platform Integration
Unreal's EOS plugin relies heavily on the Epic Games Overlay to display notifications, handle friend invites, and perform OAuth web authentications. When your game client triggers a login using the AccountPortal credential type, the operating system launches a browser window or opens the overlay.
This redirection shifts focus away from the game window. If your input modes are not set up to handle focus loss, the game can lock up or register stuck keys.
Dealing with overlay-induced input issues is a common headache for PC developers. For instance, overlay injection can conflict with raw input drivers and cause keyboard/mouse states to freeze. To prevent these bugs from ruining player experience, you can check out our analysis of The Marathon Input Issues Fix: Architecting PC Games to Survive Overlay Conflicts.
Furthermore, initialization failures during testing are often caused by misconfigured socket connections or timeout thresholds in your local configuration. If you are troubleshooting driver timeouts during session startup, check out our guide on Uefn Session Launch Timeout Nightmares: Diagnosing Unreal Engine Network Drivers.
Simplifying Cross-Platform Storefront Backends
Manually configuring storefront subsystems, writing C++ delegate chains, and dealing with platform-specific overlay focus issues is highly time-consuming. Doing this for multiple storefronts like Steam, EGS, and consoles multiplies your development overhead.
Building this yourself requires setting up load balancers, database sharding, and SSL cert management — easily 4-6 weeks of work.
With horizOn, you get a unified cross-platform backend that abstracts these storefront APIs. Instead of dealing with dual-identity tokens (EAID/PUID), Epic sandboxes, or Steamworks initialization code, you use a single API that handles user profiles, achievements, matchmaking, and leaderboards.
horizOn acts as a bridge, automatically syncing achievements and player progress with whichever storefront the user is launched from, allowing you to focus on the game loop instead of storefront boilerplate. This means your players can unlock achievements, access cloud saves, and search for matches regardless of which platform or launcher they use, without you having to write a single line of storefront-specific SDK code.
Modern Best Practices for Epic Online Services Integrations
Never Chain Asynchronous Nodes Directly: Always wait for the
OnLoginCompleteandOnQueryAchievementsCompletedelegates to fire before running downstream operations like writing stats or achievements.Enable Verbose Logging During Development: Add the following lines to your
DefaultEngine.iniunder[Core.Log]to trace hidden EOS warnings:[Core.Log] LogOnline=VeryVerbose LogOnlineGame=VeryVerbose LogEOSSDK=VeryVerboseMap Achievements to EOS in the Dev Portal: Ensure that achievements created under the Epic Games Store (EGS) are explicitly mapped to your Epic Online Services (EOS) backend. If they are not linked, the EOS SDK will not recognize the achievement ID.
Use ExchangeCode in Shipping Builds: During local development, the
Developerlogin type with a Dev Auth Tool is convenient, but you must switch the credentials type toExchangeCodein shipping builds launched from the Epic Games Launcher. Using the launcher-providedExchangeCodeauth type skips the web browser OAuth redirection, reducing login sequence duration from 8-12 seconds of manual user interaction to a sub-500ms automated handshake.
Streamlining Storefront Integrations
Resolving Epic Online Services login and achievement errors in Unreal Engine comes down to understanding the async pipeline and keeping configuration profiles perfectly aligned. By managing the transition between identity and game service interfaces, developers can eliminate silent errors and deliver a seamless player experience.
Ready to scale your multiplayer backend? Try horizOn for free or check out the API docs.