{"record":{"id":"075d6b4a48aa36d2","repo":"cube-js/cube","slug":"getclustercredentialswithiam-returned-incomplete-r","errorCode":null,"errorMessage":"GetClusterCredentialsWithIAM returned incomplete response","messagePattern":"GetClusterCredentialsWithIAM returned incomplete response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-redshift-driver/src/RedshiftIAMCredentialsProvider.ts","lineNumber":115,"sourceCode":"  }\n\n  protected async refreshCredentials(): Promise<CachedCredentials> {\n    const client = new RedshiftClient({\n      region: this.region,\n      ...(this.awsCredentials && { credentials: this.awsCredentials }),\n    });\n\n    const command = new GetClusterCredentialsWithIAMCommand({\n      ClusterIdentifier: this.clusterIdentifier,\n      DbName: this.dbName,\n      // By default, it's 15m, 1h is a maximum time\n      DurationSeconds: 1800\n    });\n\n    const response = await client.send(command);\n\n    if (!response.DbUser || !response.DbPassword || !response.Expiration) {\n      throw new Error('GetClusterCredentialsWithIAM returned incomplete response');\n    }\n\n    this.cached = {\n      user: response.DbUser,\n      password: response.DbPassword,\n      expiration: response.Expiration,\n    };\n\n    return this.cached;\n  }\n}\n","sourceCodeStart":97,"sourceCodeEnd":127,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-redshift-driver/src/RedshiftIAMCredentialsProvider.ts#L97-L127","documentation":"The Redshift IAM credentials provider calls AWS STS/Redshift GetClusterCredentialsWithIAM and requires DbUser, DbPassword, and Expiration in the response. If AWS returns a response missing any of these fields, the provider cannot build a usable connection credential, so it throws. This indicates an unexpected AWS API response rather than a Cube-side bug.","triggerScenarios":"AWS returns 200 but omits DbUser, DbPassword, or Expiration — typically when IAM permissions are partially granted (e.g. redshift:GetClusterCredentialsWithIAM allowed but the user/DB policy drops fields), when a custom Redshift credential policy filters the response, or when an AWS SDK/proxy/mocking layer returns a partial payload. Raised inside refreshCredentials during resolveCredentials on cache-miss/expiry.","commonSituations":"Misconfigured IAM policy on the assumed role; environment where an AWS LocalStack/mock or corporate proxy strips response fields; SDK version incompatibility changing response casing; temporary AWS service degradation.","solutions":["Verify the IAM identity has redshift:GetClusterCredentialsWithIAM (or GetCredentials) permitted for the cluster/dbuser resource without conditions that strip fields","Log the raw AWS response (client.send(command) result) to see which field is missing","Check the AWS SDK version used by cubejs-redshift-driver matches the Redshift Data/API expectations and returns camelCase fields","Clear the cached credential (restart the dev server) and retry — a transient AWS issue may resolve on a fresh call","If using LocalStack/mocks, ensure the GetClusterCredentialsWithIAM mock returns all three fields"],"exampleFix":"// before (partial IAM policy response)\nconst response = await client.send(command);\nthis.cached = { user: response.DbUser, ... }; // DbUser undefined -> throws\n// after (ensure policy grants credential fields)\n// IAM policy statement: {\"Effect\":\"Allow\",\"Action\":\"redshift:GetClusterCredentialsWithIAM\",\"Resource\":[\"arn:aws:redshift:...:dbuser:cluster/*\",\"arn:aws:redshift:...:dbname:cluster/*\"]}","handlingStrategy":"retry","validationCode":"// Wrap credential resolution and verify fields\nconst response = await client.send(command);\nif (!response?.DbUser || !response?.DbPassword || !response?.Expiration) {\n  // fail fast with diagnostic before Cube throws\n  console.error('GetClusterCredentialsWithIAM missing fields:', Object.keys(response || {}));\n}","typeGuard":"function hasFullCredentials(r) {\n  return !!r && typeof r.DbUser === 'string' && !!r.DbUser &&\n         typeof r.DbPassword === 'string' && !!r.DbPassword &&\n         r.Expiration instanceof Date;\n}","tryCatchPattern":"try {\n  await dataSource.refreshCredentials();\n} catch (e) {\n  if (e.message.includes('incomplete response')) {\n    // check IAM policy / retry after backoff\n    await new Promise(r => setTimeout(r, 1000));\n    return dataSource.refreshCredentials();\n  }\n  throw e;\n}","preventionTips":["Grant redshift:GetClusterCredentialsWithIAM fully (dbuser and dbname resources) with no field-stripping conditions","Avoid mocks/proxies for the Redshift credentials endpoint in production paths","Keep the AWS SDK version in cubejs-redshift-driver current","Monitor for this error and alert on repeated occurrences (signals IAM drift)"],"tags":["redshift","aws","iam","credentials","driver"],"backgroundTag":"incomplete-credentials-response","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}