Quick answer: Family Share crashes almost always come from conflating the playing user (GetSteamID) with the owning account. Tag crashes with BIsSubscribedFromFamilySharing, audit every SteamID read, test DLC paths with and without ownership, and verify your save path survives a forced shutdown when the owner reclaims the license.

Steam Family Sharing lets one account lend its library to up to five others. It is a great feature and an enormous source of edge-case bugs. Family Share sessions are not quite the same as a regular launch: the identity presented by Steamworks APIs can split between the logged-in user and the license owner, cloud saves can desync in surprising ways, DLC ownership lives on a different account than the player, and the entire session can be terminated from above when the owner fires up Steam. If any of your code paths assume a single consistent identity, Family Share will break them. This post walks through what breaks and how to fix it.

Two Identities, Not One

In a regular launch, the user running the game and the account that owns the game are the same person. In a Family Share launch, they are different. The APIs split accordingly:

ISteamUser::GetSteamID returns the playing user. This is the person in front of the computer, the one whose profile, friends list, and cloud storage you should integrate with.

ISteamApps::BIsSubscribedFromFamilySharing returns true on a borrowed session. ISteamApps::GetAppOwner returns the owning account’s SteamID. Licensing checks, DLC queries, and stats tied to product entitlement should key off the owner.

Most Family Share bugs are one of two shapes: code that used the playing user ID for a licensing check, or code that used the owner ID for anything user-facing. Both look fine on a regular launch because the two IDs are equal. Both explode on a borrowed one.

Tag Every Crash Report

Before you debug anything, make Family Share visible in your telemetry. Read the flag at startup and attach it to every crash and telemetry event:

bool isFamilyShare = SteamApps()->BIsSubscribedFromFamilySharing();
CSteamID playing = SteamUser()->GetSteamID();
CSteamID owner   = SteamApps()->GetAppOwner();

SetCrashAnnotation("family_share", isFamilyShare ? "1" : "0");
SetCrashAnnotation("playing_id", playing.ConvertToUint64());
SetCrashAnnotation("owner_id",   owner.ConvertToUint64());

Now you can slice crash rates by Family Share state. If the rate is materially higher on borrowed sessions, you have identity-confusion bugs to hunt. If it is identical, Family Share is not the problem and you can stop here.

Audit Every SteamID Read

Grep your codebase for every call to GetSteamID, GetAppOwner, and any cached SteamID fields. Classify each call into one of two categories:

Player-facing operations (saves, stats, social, UI avatar): these use the playing user ID. Never the owner.

License-checking operations (DLC ownership, entitlement, purchase verification): these use the owner ID, because DLC is tied to the account that bought it.

If a call does both in the same function, split it. Name the variables playingUser and owningAccount explicitly so future maintainers cannot accidentally reintroduce the bug.

DLC Ownership on Borrowed Sessions

A borrower plays the base game with the owner’s license. They do not inherit the owner’s DLC. A borrower who owns no DLC plays the vanilla game; a borrower who personally bought DLC plays with that DLC active. Any code that checks DLC via BIsDlcInstalled returns based on the local disk state, which will return true for DLC the owner installed but the borrower does not own.

The correct check is BIsSubscribedApp(dlcAppID) against the current user’s entitlement. This returns the actual ownership for the playing session, accounting for Family Share correctly.

bool HasDLC(AppId_t dlcId) {
    return SteamApps()->BIsSubscribedApp(dlcId);
    // NOT BIsDlcInstalled — that returns true for any borrower.
}

Run through every DLC gate in your game with a borrowed session that does not own the DLC. The classic bug is a content-load crash when the game assumes DLC assets are present because they were installed by the owner.

Cloud Saves Across Accounts

Cloud saves live on the playing user’s account, not the owner’s. This is the correct behavior — you do not want one person’s save to clobber another’s — but it introduces real-world edge cases:

A player borrows the game from their brother and plays a fresh save on their own cloud. The brother loads the game the next day; his save is untouched. Both saves exist independently. This works.

A player borrows, starts a save that writes locally (not to cloud because they skipped the sync prompt), and later the owner reclaims and starts their own save. The local save is still on disk. If your game reads local-first without checking the current account ID, the owner may load the borrower’s save by accident. Fix: write the account ID into each save file and refuse to load a save whose ID does not match the current player.

Shadow Launches and Forced Termination

Family Share has one more twist: the license is reclaimable. If the owner launches any Steam game while the borrower is playing, the borrower gets a five-minute warning and their session is terminated. Your code must survive this without losing the player’s progress.

Two defenses: checkpoint aggressively (autosave at every natural break so the most recent save is at most a few minutes old), and flush-on-shutdown cleanly when you receive the FamilySharingStopPlaying_t callback or a standard app-quit signal. Do not rely on a graceful shutdown path that takes ten seconds to run; the OS will kill you after five.

STEAM_CALLBACK(MyClient, OnStopPlaying, RemoteStoragePublishedFileUnsubscribed_t) {
    FlushSaveSync(SAVE_REASON_FAMILY_SHARE_REVOKED);
    ShowMessage("Owner is playing. Your progress has been saved.");
    RequestQuit();
}

Testing Family Share in Dev

To reproduce Family Share locally, you need two Steam accounts on two machines. The owner enables Family Sharing in settings and authorizes the borrower’s machine. The borrower logs in and sees the library. Most bugs become obvious within five minutes of actually running the flow.

If you cannot set up real Family Share, Steamworks offers a dev mode where you can force BIsSubscribedFromFamilySharing to return true for testing. Use this for CI; use a real borrowed session for manual QA before release.

“Our first release had a 3% crash rate on Family Share launches and a 0.1% rate everywhere else. The culprit was one cached SteamID used for DLC checks. One line fix, one flag added to crash reports, and we never missed that bug again.”

Related Issues

For a broader look at Steam-specific integration bugs, read automated crash reporting for indie games. For handling platform-specific crash telemetry, see how to build a crash report deduplication system.

The playing user and the owning account are two different people. Code like they are, even when they happen to be the same.