{"record":{"id":"b172cf7b9d3f9c68","repo":"FlowiseAI/Flowise","slug":"sts-assumerole-returned-incomplete-credentials","errorCode":null,"errorMessage":"STS AssumeRole returned incomplete credentials","messagePattern":"STS AssumeRole returned incomplete credentials","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/src/awsToolsUtils.ts","lineNumber":179,"sourceCode":"        }\n    }\n\n    const stsClient = new STSClient(stsConfig)\n\n    const assumeRoleInput: AssumeRoleCommandInput = {\n        RoleArn: roleArn,\n        RoleSessionName: `FlowiseSession-${Date.now()}`\n    }\n\n    if (externalId) {\n        assumeRoleInput.ExternalId = externalId\n    }\n\n    try {\n        const response = await stsClient.send(new AssumeRoleCommand(assumeRoleInput))\n\n        if (!response.Credentials?.AccessKeyId || !response.Credentials?.SecretAccessKey || !response.Credentials?.SessionToken) {\n            throw new Error('STS AssumeRole returned incomplete credentials')\n        }\n\n        return {\n            accessKeyId: response.Credentials.AccessKeyId,\n            secretAccessKey: response.Credentials.SecretAccessKey,\n            sessionToken: response.Credentials.SessionToken\n        }\n    } catch (error) {\n        if (error instanceof Error && error.message === 'STS AssumeRole returned incomplete credentials') {\n            throw error\n        }\n        const rawMessage = error instanceof Error ? error.message : String(error)\n        // Log full error server-side for operator debugging (includes IAM principal ARNs, account IDs, etc.)\n        if (logger) {\n            logger.error(`[AWS STS] AssumeRole failed for role \"${roleArn}\": ${rawMessage}`)\n        }\n        // Return sanitized error to user — no raw STS message that may contain internal infrastructure details\n        throw new Error(","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/awsToolsUtils.ts#L161-L197","documentation":"After stsClient.send(AssumeRoleCommand) succeeds, the code requires response.Credentials to contain AccessKeyId, SecretAccessKey, AND SessionToken. If any of the three is missing/empty it throws. The AWS SDK normally returns all three on a successful AssumeRole, so this is an unusual partial-response condition, often from an emulator, a proxy mangling the XML, or an SDK deserialization mismatch.","triggerScenarios":"STS-compatible mock/emulator (LocalStack, moto) returns a Credentials object missing a field; a proxy strips part of the response body; an SDK version mismatch deserializes incompletely; transient partial response from a non-AWS STS endpoint.","commonSituations":"Local testing against LocalStack/moto that returns partial credentials; transparent proxy modifying the STS XML/JSON response; pinning to an @aws-sdk/client-sts version with a known deserialization regression.","solutions":["If using a mock/emulator, ensure it returns AccessKeyId, SecretAccessKey, and SessionToken in Credentials.","Retry once — transient partial responses are rare but possible.","Upgrade or pin @aws-sdk/client-sts to a known-good version.","Verify no proxy is altering the STS response body.","Confirm you are hitting real AWS STS (or a faithful emulator) for the partition."],"exampleFix":"// before (mock returns partial)\n{ Credentials: { AccessKeyId: 'ASIA...', SecretAccessKey: '...' } } // no SessionToken\n\n// after (mock returns full)\n{ Credentials: { AccessKeyId: 'ASIA...', SecretAccessKey: '...', SessionToken: 'IQo...' } }","handlingStrategy":"retry","validationCode":"// Validate the (mock) STS response shape during tests\nfunction assertAssumeRoleResponse(resp) {\n    const c = resp.Credentials\n    if (!c?.AccessKeyId || !c?.SecretAccessKey || !c?.SessionToken) {\n        throw new Error('STS mock must return AccessKeyId, SecretAccessKey, and SessionToken')\n    }\n}","typeGuard":"function hasCompleteCredentials(resp) {\n    const c = resp?.Credentials\n    return Boolean(c?.AccessKeyId && c?.SecretAccessKey && c?.SessionToken)\n}","tryCatchPattern":"// Retry once on the rare partial-response case\nasync function assumeRoleSafe(input) {\n    try {\n        return await assumeRole(input)\n    } catch (e) {\n        if (/incomplete credentials/i.test(e.message)) {\n            return await assumeRole(input) // single retry\n        }\n        throw e\n    }\n}","preventionTips":["Ensure STS emulators (LocalStack/moto) return all three credential fields.","Pin @aws-sdk/client-sts to a known-good version in CI.","Verify no proxy alters the STS response body."],"tags":["aws","sts","assume-role","credentials","sdk"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}