LykosAI/StabilityMatrix · error · InvalidOperationException

GetUserAccount did not contain an id

Error message

GetUserAccount did not contain an id

What it means

During Civitai account linking, AccountsService fetches the user account with the provided API token and requires the response JSON to contain an id, which is used for the follow-up GetUserById lookup. If the Civitai TRPC response lacks an id, the service throws this InvalidOperationException because it cannot persist a valid CivitApi token record.

Solutions

  1. Verify the Civitai API token is valid and active (test it against Civitai) before calling CivitLoginAsync
  2. Inspect the GetUserAccount response shape and update the CivitTRPCApi parsing if Civitai changed its schema
  3. Catch InvalidOperationException and prompt the user to re-enter a valid API token

Example fix

// before
await accountsService.CivitLoginAsync(userProvidedToken);
// after
var account = await civitTRPCApi.GetUserAccount(userProvidedToken);
if (account.InnerJson?.Id is null)
{
    throw new InvalidOperationException("Civitai token was rejected or returned no account id; check the API key");
}
await accountsService.CivitLoginAsync(userProvidedToken);
Defensive patterns

Strategy: validation

Validate before calling

var probe = await civitTRPCApi.GetUserAccount(apiToken);
if (probe.InnerJson?.Id is null)
    throw new InvalidOperationException("Token rejected or response missing id; verify the Civitai API key");

Type guard

bool HasAccountId(CivitUserAccount a) => a.InnerJson?.Id is not null;

Try / catch

try
{
    await accountsService.CivitLoginAsync(apiToken);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("GetUserAccount did not contain an id"))
{
    // surface 'invalid Civitai API token' to the user
}

Prevention

When it happens

Trigger: Calling AccountsService.CivitLoginAsync(apiToken) when the Civitai GetUserAccount response's InnerJson has no Id — typically because the token is invalid/expired, the API shape changed, or a non-authenticated response was returned.

Common situations: User pastes a revoked or mistyped Civitai API key; Civitai API contract change or partial outage returning a body without the expected json.id; rate-limited or error response parsed as a user account.

Related errors


AI-assisted analysis of LykosAI/StabilityMatrix@af93d6ef57 (2026-09-12). Data as JSON: /api/errors/780d5b7d748d0913. Report an issue: GitHub.

Appendix: source

Thrown at StabilityMatrix.Avalonia/Services/AccountsService.cs:175

            throw new InvalidOperationException(
                "Lykos account must be connected in to manage OAuth connections"
            );
        }

        await lykosAuthApiV2.ApiV2OauthPatreon();

        await RefreshLykosAsync(secrets);
    }

    public async Task CivitLoginAsync(string apiToken)
    {
        var secrets = await secretsManager.SafeLoadAsync();

        // Get id first using the api token
        var userAccount = await civitTRPCApi.GetUserAccount(bearerToken: apiToken);
        var id =
            userAccount.InnerJson?.Id
            ?? throw new InvalidOperationException("GetUserAccount did not contain an id");

        // Then get the username using the id
        var account = await civitTRPCApi.GetUserById(new CivitGetUserByIdRequest { Id = id }, apiToken);
        var username = account.Result.Data.Json.Username;

        secrets = secrets with { CivitApi = new CivitApiTokens(apiToken, username) };

        await secretsManager.SaveAsync(secrets);

        await RefreshCivitAsync(secrets);
    }

    /// <inheritdoc />
    public async Task CivitLogoutAsync()
    {
        var secrets = await secretsManager.SafeLoadAsync();
        await secretsManager.SaveAsync(secrets with { CivitApi = null });

View on GitHub (pinned to af93d6ef57)