ruvnet/ruflo · error · NotLoggedInError

not logged in for profile

Error message

not logged in for profile "${profile}" — run: ruflo auth login --profile ${profile}

What it means

getValidAccessToken(profileName) throws NotLoggedInError when getProfile(profileName) returns nothing — there is no stored auth profile for that name. The message includes the exact remediation command. Profiles are created by `ruflo auth login`; asking for a profile that never logged in (or a typo'd name) hits this immediately, before any network traffic.

Solutions

  1. Run the command from the message: ruflo auth login --profile <profile>
  2. Check which profiles exist first: ruflo auth status
  3. If the name was a typo, call getValidAccessToken with the exact profile name you logged in as
  4. On ephemeral CI machines, perform a login step (e.g. --token-stdin) before any authenticated command
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap pre-check: run `ruflo auth status` (offline-safe) and assert the profile is listed
const status = await runRuflo(['auth', 'status', '--json']);
if (!status.profiles.includes(profileName)) await runRuflo(['auth', 'login', '--profile', profileName]);

Type guard

import { NotLoggedInError } from '@claude-flow/cli/dist/auth/client.js';
function isNotLoggedIn(e: unknown): e is NotLoggedInError {
  return e instanceof Error && e.name === 'NotLoggedInError';
}

Try / catch

try {
  token = await getValidAccessToken(profileName);
} catch (e) {
  if (isNotLoggedIn(e)) {
    console.error(e.message); // already contains the exact login command
    process.exit(3);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getValidAccessToken('work') when only the 'default' profile exists; calling with the default when no login ever happened; a typo or case-mismatched profile name ('Default' vs 'default'); the profile state file was deleted or never created on a fresh machine/CI container.

Common situations: New machine or CI runner with no prior `ruflo auth login`; scripts hard-coding a profile name that doesn't match what the user created; state directory removed during cleanup (~/.claude-flow or equivalent wiped); switching between accounts and forgetting to log in under the new profile.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/42e7f81f81e8228f. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/auth/client.ts:239

      throw new Error(`Cognitum auth service returned an unexpected response: ${e.message}`);
    }
    throw e;
  }
}

/**
 * Returns an access token suitable for an authenticated call.
 *
 * Fast path: a process-memory token with more than one minute remaining.
 * Slow path: load the profile's refresh token from the OS keychain, perform
 * one refresh, persist a rotated refresh token BEFORE exposing the new access
 * token, then update metadata and the process cache. Refresh is deliberately
 * demand-driven: offline-safe commands such as plain `auth status` never call
 * this function and therefore never create background traffic or retry loops.
 */
export async function getValidAccessToken(profileName = 'default'): Promise<string> {
  const profile = getProfile(profileName);
  if (!profile) throw new NotLoggedInError(profileName);

  const scopesWithoutConsent = profile.scopes.filter((scope) => {
    const domain = domainForScope(scope);
    return domain !== undefined && !hasConsent(domain);
  });
  if (scopesWithoutConsent.length > 0) {
    throw new ScopeConsentMismatchError(profileName, scopesWithoutConsent);
  }

  const cached = getSessionToken(profileName, ACCESS_TOKEN_REFRESH_WINDOW_MS);
  if (cached) return cached;
  if (!profile.keychainRef) throw new SessionOnlyExpiredError(profileName);

  const sec = await loadSecurityOAuth();
  const keychain = await sec.createKeychainAdapter();
  const refreshTokenValue = await keychain.getSecret(KEYCHAIN_SERVICE, profile.keychainRef);
  if (!refreshTokenValue) throw new SessionOnlyExpiredError(profileName);

View on GitHub (pinned to fa13ee4ad6)