{"record":{"id":"dcaaa64a0721541c","repo":"can1357/oh-my-pi","slug":"assume-role","errorCode":"assume-role","errorMessage":"AWS AssumeRole failed: ${response.status} ${xmlTag(xml, \"Message\") ?? xml.slice(0, 200)}","messagePattern":"AWS AssumeRole failed: (.+?) (.+?)","errorType":"error_code","errorClass":"AIError.AwsCredentialsError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/aws-credentials.ts","lineNumber":397,"sourceCode":"\tconst signed = await signRequest({\n\t\tmethod: \"POST\",\n\t\thost: endpoint.host,\n\t\tpath: endpoint.pathname,\n\t\tbody: payload,\n\t\tregion,\n\t\tservice: \"sts\",\n\t\tcredentials: base,\n\t\theaders: { \"content-type\": contentType },\n\t});\n\tconst response = await fetchImpl(endpoint, {\n\t\tmethod: \"POST\",\n\t\theaders: { ...signed, \"content-type\": contentType },\n\t\tbody: payload,\n\t\tsignal,\n\t});\n\tconst xml = await response.text();\n\tif (!response.ok) {\n\t\tthrow new AIError.AwsCredentialsError(\n\t\t\t`AWS AssumeRole failed: ${response.status} ${xmlTag(xml, \"Message\") ?? xml.slice(0, 200)}`,\n\t\t\t\"assume-role\",\n\t\t);\n\t}\n\treturn parseStsCredentials(xml, \"AWS AssumeRole\", \"assume-role\");\n}\n\ninterface SsoCachedToken {\n\taccessToken?: string;\n\texpiresAt?: string;\n\tstartUrl?: string;\n\tregion?: string;\n}\n\nasync function readSsoCredentials(\n\tprofileCfg: Record<string, string>,\n\tconfigIni: AwsIniFile | undefined,\n\tdefaultRegion: string,","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/aws-credentials.ts#L379-L415","documentation":"This error is thrown when an AWS STS AssumeRole API call made while resolving a profile's role_arn returns a non-OK HTTP status. The library SigV4-signs the request with the base (source) credentials and posts it to the regional STS endpoint; STS rejected the exchange, so no temporary role credentials can be returned. The message embeds the HTTP status and the STS error Message extracted from the XML response body (or the first 200 chars of raw XML).","triggerScenarios":"stsAssumeRole() receives response.ok === false from the STS endpoint. Typical causes: base credentials lack sts:AssumeRole permission on the target role (AccessDenied), wrong role_arn, invalid/mismatched external_id, duration_seconds outside 900-43200, expired or untrusted source credentials (ExpiredToken/InvalidClientTokenId), or wrong region for the STS endpoint.","commonSituations":"Cross-account role assumption where the trust policy's ExternalId doesn't match the profile's external_id; IAM policy missing sts:AssumeRole on the role ARN; typos in role_arn in ~/.aws/config; using a region whose STS endpoint the account hasn't enabled; stale long-lived keys rotated or revoked; role trust policy not listing the source principal.","solutions":["Read the embedded STS Message in the error: AccessDenied -> fix IAM/trust policy, ExternalId -> align profile external_id with trust policy, ExpiredToken -> refresh base credentials","Verify role_arn, external_id, duration_seconds, and source_profile/credential_source in ~/.aws/config","Confirm the base credentials are valid: aws sts get-caller-identity with those credentials","Confirm the IAM identity has sts:AssumeRole allowed on the target role and the role's trust policy allows the source principal","Test the same chain with `aws sts assume-role --role-arn ...` to confirm it's a config issue, not library-specific"],"exampleFix":"// before (~/.aws/config)\n[profile deploy]\nrole_arn = arn:aws:iam::123456789012:role/Deploy\nsource_profile = base\nduration_seconds = 72000 // invalid: max 43200\n\n// after\n[profile deploy]\nrole_arn = arn:aws:iam::123456789012:role/Deploy\nsource_profile = base\nduration_seconds = 3600","handlingStrategy":"try-catch","validationCode":"// Pre-check base credentials are live before assuming the role:\nimport { $ } from \"bun\";\nconst r = await $`aws sts get-caller-identity`.quiet().nothrow();\nif (r.exitCode !== 0) throw new Error(\"Base AWS credentials invalid; fix source_profile/keys before AssumeRole\");","typeGuard":"function isAssumeRoleError(err: unknown): err is Error & { code: string } {\n  return err instanceof Error && \"code\" in err && (err as { code?: string }).code === \"assume-role\";\n}","tryCatchPattern":"try {\n  creds = await resolveProfileChain(profile);\n} catch (err) {\n  if (isAssumeRoleError(err)) {\n    // message embeds HTTP status + STS Message; surface to user with profile name\n    logger.error(\"STS AssumeRole rejected\", { profile, detail: err.message });\n  }\n  throw err;\n}","preventionTips":["Always test the profile chain with `aws sts assume-role` / the AWS CLI before wiring it into automation","Keep source_profile credentials fresh and ensure IAM allows sts:AssumeRole on the target role","Match external_id in the profile to the role trust policy exactly","Keep duration_seconds within 900-43200 and at or below the role's MaxSessionDuration","Use the correct region so the regional STS endpoint is enabled for the account"],"tags":["aws","sts","iam","authentication","network"],"backgroundTag":"aws-assume-role-denied","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}