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
- Run `aws sso login --profile <profile>` (or `aws sso login` with the matching sso-session) to populate ~/.aws/sso/cache, then retry
- Verify the profile's sso_start_url / sso_session matches the one you actually logged in to
- Check ~/.aws/sso/cache exists and contains JSON files with accessToken, and that you run under the same HOME user
- 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
- Run `aws sso login` for the exact profile/session before using SSO profiles
- Keep the same HOME/user between login and application runtime (esp. in containers/CI)
- Seed CI caches with a fresh SSO token at pipeline start
- Confirm sso_start_url in the profile matches the portal you logged into
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
- sso-token-expired
- sso-role
- assume-role
- Failed to load tree-sitter language: {err}
- Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7cdcd4dd10193cbb.
Report an issue: GitHub.