{"record":{"id":"6b4f3c615b6f9393","repo":"can1357/oh-my-pi","slug":"web-identity","errorCode":"web-identity","errorMessage":"Unable to read AWS web identity token file: ${String(err)}","messagePattern":"Unable to read AWS web identity token file: (.+?)","errorType":"error_code","errorClass":"AIError.AwsCredentialsError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/aws-credentials.ts","lineNumber":766,"sourceCode":"\t);\n}\n\n/**\n * Exchange a web-identity token file for role credentials via STS\n * `AssumeRoleWithWebIdentity`. Used by the env chain (`AWS_WEB_IDENTITY_TOKEN_FILE`)\n * and by `role_arn` + `web_identity_token_file` profiles.\n */\nasync function assumeRoleWithWebIdentity(\n\tparams: { roleArn: string; tokenFile: string; sessionName?: string },\n\tregion: string,\n\tsignal: AbortSignal | undefined,\n\tfetchImpl: FetchImpl,\n): Promise<ResolvedCredentials> {\n\tlet token: string;\n\ttry {\n\t\ttoken = (await Bun.file(params.tokenFile).text()).trim();\n\t} catch (err) {\n\t\tthrow new AIError.AwsCredentialsError(\n\t\t\t`Unable to read AWS web identity token file: ${String(err)}`,\n\t\t\t\"web-identity\",\n\t\t\t{\n\t\t\t\tcause: err,\n\t\t\t},\n\t\t);\n\t}\n\tif (!token) {\n\t\tthrow new AIError.AwsCredentialsError(\"AWS web identity token file is empty.\", \"web-identity\");\n\t}\n\tconst body = new URLSearchParams({\n\t\tAction: \"AssumeRoleWithWebIdentity\",\n\t\tVersion: \"2011-06-15\",\n\t\tRoleArn: params.roleArn,\n\t\tRoleSessionName: params.sessionName || `omp-${process.pid}`,\n\t\tWebIdentityToken: token,\n\t});\n\tconst response = await fetchImpl(stsEndpoint(region), {","sourceCodeStart":748,"sourceCodeEnd":784,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/aws-credentials.ts#L748-L784","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: env copied into local shell\nAWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token  # not mounted locally\n\n// after: unset outside the cluster\nunset AWS_WEB_IDENTITY_TOKEN_FILE AWS_ROLE_ARN","handlingStrategy":"validation","validationCode":"import { isEnoent } from \"@oh-my-pi/pi-utils\";\nasync function canReadTokenFile(path) {\n  try {\n    const t = (await Bun.file(path).text()).trim();\n    return t.length > 0;\n  } catch (err) {\n    return false;\n  }\n}\n// guard env before entering the web-identity path\nif (process.env.AWS_WEB_IDENTITY_TOKEN_FILE && !(await canReadTokenFile(process.env.AWS_WEB_IDENTITY_TOKEN_FILE))) {\n  throw new Error(`AWS_WEB_IDENTITY_TOKEN_FILE unreadable: ${process.env.AWS_WEB_IDENTITY_TOKEN_FILE}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const creds = await resolveAwsCredentials();\n} catch (err) {\n  if (err instanceof AIError.AwsCredentialsError && err.code === \"web-identity\" && /Unable to read AWS web identity token file/.test(err.message)) {\n    logger.error(\"Web identity token file unreadable — check mount/permissions or unset AWS_WEB_IDENTITY_TOKEN_FILE\", { cause: err });\n  } else throw err;\n}","preventionTips":["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."],"tags":["aws","web-identity","file-io","irsa"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}