can1357/oh-my-pi · error · AIError.AwsCredentialsError
web-identity
web-identity
Error message
Unable to read AWS web identity token file: ${String(err)} What it means
When using IAM roles for service accounts (IRSA) or similar web-identity flows, the library reads the JWT from the file named by AWS_WEB_IDENTITY_TOKEN_FILE. If Bun.file(...).text() throws (missing file, permissions, wrong path), the original error is wrapped in an AwsCredentialsError with kind "web-identity" and attached as cause.
Source
Thrown at packages/ai/src/providers/aws-credentials.ts:766
);
}
/**
* Exchange a web-identity token file for role credentials via STS
* `AssumeRoleWithWebIdentity`. Used by the env chain (`AWS_WEB_IDENTITY_TOKEN_FILE`)
* and by `role_arn` + `web_identity_token_file` profiles.
*/
async function assumeRoleWithWebIdentity(
params: { roleArn: string; tokenFile: string; sessionName?: string },
region: string,
signal: AbortSignal | undefined,
fetchImpl: FetchImpl,
): Promise<ResolvedCredentials> {
let token: string;
try {
token = (await Bun.file(params.tokenFile).text()).trim();
} catch (err) {
throw new AIError.AwsCredentialsError(
`Unable to read AWS web identity token file: ${String(err)}`,
"web-identity",
{
cause: err,
},
);
}
if (!token) {
throw new AIError.AwsCredentialsError("AWS web identity token file is empty.", "web-identity");
}
const body = new URLSearchParams({
Action: "AssumeRoleWithWebIdentity",
Version: "2011-06-15",
RoleArn: params.roleArn,
RoleSessionName: params.sessionName || `omp-${process.pid}`,
WebIdentityToken: token,
});
const response = await fetchImpl(stsEndpoint(region), {View on GitHub (pinned to 9690622007)
Solutions
- Check the path in AWS_WEB_IDENTITY_TOKEN_FILE exists and is readable: cat "$AWS_WEB_IDENTITY_TOKEN_FILE".
- If running outside the intended environment (K8s/EKS), unset AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN so the resolver falls back to other credential methods.
- In containers, mount the service-account token volume or pass the projected token file path correctly.
- Fix file permissions or replace an expired/rotated projected token file.
Example fix
// before: env copied into local shell AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token # not mounted locally // after: unset outside the cluster unset AWS_WEB_IDENTITY_TOKEN_FILE AWS_ROLE_ARN
Defensive patterns
Strategy: validation
Validate before calling
import { isEnoent } from "@oh-my-pi/pi-utils";
async function canReadTokenFile(path) {
try {
const t = (await Bun.file(path).text()).trim();
return t.length > 0;
} catch (err) {
return false;
}
}
// guard env before entering the web-identity path
if (process.env.AWS_WEB_IDENTITY_TOKEN_FILE && !(await canReadTokenFile(process.env.AWS_WEB_IDENTITY_TOKEN_FILE))) {
throw new Error(`AWS_WEB_IDENTITY_TOKEN_FILE unreadable: ${process.env.AWS_WEB_IDENTITY_TOKEN_FILE}`);
} Try / catch
try {
const creds = await resolveAwsCredentials();
} catch (err) {
if (err instanceof AIError.AwsCredentialsError && err.code === "web-identity" && /Unable to read AWS web identity token file/.test(err.message)) {
logger.error("Web identity token file unreadable — check mount/permissions or unset AWS_WEB_IDENTITY_TOKEN_FILE", { cause: err });
} else throw err;
} Prevention
- Verify token file readability at process startup when the env var is present.
- Unset AWS_WEB_IDENTITY_TOKEN_FILE/AWS_ROLE_ARN outside the intended runtime (local dev).
- Mount the service-account token volume explicitly in container manifests.
- Check the cause attached to the error for the exact filesystem failure.
When it happens
Trigger: assumeRoleWithWebIdentity is invoked because AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN are set, but the token file path does not exist, is unreadable (permissions), points to a directory, or the filesystem mount (e.g. projected service-account token volume) is unavailable.
Common situations: Running a container locally (docker run) where the /var/run/secrets/eks.amazonaws.com/serviceaccount/token mount was not passed; env var copied into a dev shell without the file existing; Kubernetes pod where the service account token volume is not mounted; typo in AWS_WEB_IDENTITY_TOKEN_FILE path.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}
- Bedrock response has no body
- exceptionType
- code
- ${source} response has a missing or invalid Expiration.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6b4f3c615b6f9393.
Report an issue: GitHub.