can1357/oh-my-pi · error · AIError.AwsCredentialsError

sso-token-missing

sso-token-missing

Error message

AWS SSO token for ${startUrl} not found in ~/.aws/sso/cache. Run 'aws sso login' first.

What it means

Thrown when an AWS SSO-based profile requires a bearer token but no cached SSO token with an access token exists in ~/.aws/sso/cache for the profile's start URL. The library only reads pre-cached tokens created by the AWS CLI; it never initiates an SSO login flow. Without the token it cannot call the SSO portal federation API to get role credentials.

Source

Thrown at packages/ai/src/providers/aws-credentials.ts:436

): Promise<ResolvedCredentials | undefined> {
	// Two SSO profile shapes:
	//   - legacy: `sso_start_url` + `sso_region` directly on the profile
	//   - sso-session: `sso_session = my-session` references a `[sso-session my-session]` block
	let startUrl = profileCfg.sso_start_url;
	let ssoRegion = profileCfg.sso_region;
	const sessionName = profileCfg.sso_session;
	if (sessionName && configIni) {
		const session = configIni[`sso-session:${sessionName}`];
		if (session) {
			startUrl = startUrl || session.sso_start_url;
			ssoRegion = ssoRegion || session.sso_region;
		}
	}
	if (!startUrl || !ssoRegion) return undefined;

	const token = await loadSsoCachedToken(startUrl, sessionName);
	if (!token?.accessToken) {
		throw new AIError.AwsCredentialsError(
			`AWS SSO token for ${startUrl} not found in ~/.aws/sso/cache. Run 'aws sso login' first.`,
			"sso-token-missing",
		);
	}
	const expiresAt = token.expiresAt ? Date.parse(token.expiresAt) : Number.POSITIVE_INFINITY;
	if (Number.isFinite(expiresAt) && expiresAt <= Date.now()) {
		throw new AIError.AwsCredentialsError(
			`AWS SSO token for ${startUrl} has expired. Run 'aws sso login' to refresh.`,
			"sso-token-expired",
		);
	}

	const url =
		`https://portal.sso.${ssoRegion}.amazonaws.com/federation/credentials` +
		`?account_id=${encodeURIComponent(profileCfg.sso_account_id)}` +
		`&role_name=${encodeURIComponent(profileCfg.sso_role_name)}`;
	const response = await fetchImpl(url, {
		method: "GET",

View on GitHub (pinned to 9690622007)

Solutions

  1. Run `aws sso login --profile <profile>` (or `aws sso login` with the matching sso-session) to populate ~/.aws/sso/cache, then retry
  2. Verify the profile's sso_start_url / sso_session matches the one you actually logged in to
  3. Check ~/.aws/sso/cache exists and contains JSON files with accessToken, and that you run under the same HOME user
  4. In CI, run `aws sso login` (with device-code flow or a pre-seeded cache) before using SSO profiles

Example fix

// before
// running the app with an SSO profile on a fresh machine -> error

// after
$ aws sso login --profile my-sso-profile
$ # then run the app again
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
// Run before resolving an SSO profile:
const cacheDir = path.join(os.homedir(), ".aws", "sso");
const hasToken = fs.existsSync(path.join(cacheDir, "cache")) &&
  fs.readdirSync(path.join(cacheDir, "cache")).some(f => {
    try { return !!JSON.parse(fs.readFileSync(path.join(cacheDir, "cache", f), "utf8")).accessToken; }
    catch { return false; }
  });
if (!hasToken) throw new Error("Run `aws sso login --profile <profile>` first");

Type guard

function hasSsoToken(t: unknown): t is { accessToken: string; expiresAt?: string } {
  return typeof t === "object" && t !== null && typeof (t as { accessToken?: unknown }).accessToken === "string";
}

Prevention

When it happens

Trigger: readSsoCredentials() resolves a profile with sso_start_url/sso_region (or an sso_session block), calls loadSsoCachedToken(), and gets undefined or a token without accessToken — i.e. `aws sso login` was never run, the cache directory doesn't exist, or the cache was cleared.

Common situations: Fresh machine or CI container where ~/.aws/sso/cache was never populated; user logged into a different start URL than the profile's; running as a different user so HOME points elsewhere; cache wiped by cleanup scripts; using an sso-session whose cached token file was deleted.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/7cdcd4dd10193cbb. Report an issue: GitHub.