question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

(appsync): Cross-stack resources -> Fn::GetAtt references undefined

See original GitHub issue

I have 2 stacks:

  • API-stack which contains the Appsync API
  • SQS-stack, which contains a SQS resource (other stack are removed for simplicity)

I want to simply pass the SQS queue (defined in the SQS stack) to the API stack

The code synthesizes correctly, but it fails at deployment with error:

 ❌  AaaApiStack failed: Error [ValidationError]: Template error: instance of Fn::GetAtt references undefined resource StudentQueue68D52AA1
    at Request.extractError (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:690:12)
    at Request.callListeners (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'ValidationError',
  time: 2021-01-31T13:22:49.329Z,
  requestId: '7f7feb96-4b35-46b1-bc67-e3c3f0d1aa2f',
  statusCode: 400,
  retryable: false,
  retryDelay: 445.1091591510583
}
Template error: instance of Fn::GetAtt references undefined resource StudentQueue68D52AA1

Reproduction Steps

cdk.ts

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import { SQSStack } from "../lib/sqs/stack";
import { ApiStack } from "../lib/api/stack";
const app = new cdk.App();

const env = {
  region: "us-east-1",
  account: "446416672052",
};
const SQSStack = new SQSStack(
  app,
  "AaaSQSStack",
  {
    env,
  }
);

const apiStack = new ApiStack(app, "AaaApiStack", {
  env,
  SQSSqs: SQSStack.studentQueue,
});

API-stack

import * as cdk from "@aws-cdk/core";
import * as node from "@aws-cdk/aws-lambda-nodejs";
import * as appsync from "@aws-cdk/aws-appsync";

import * as sqs from "@aws-cdk/aws-sqs";
import { ResolvableField } from "@aws-cdk/aws-appsync";
import * as fs from "fs";
import { join } from "path";

export interface ApiStackProps extends cdk.StackProps {
  SQSSqs: sqs.IQueue;
}

export class ApiStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props: ApiStackProps) {
    super(scope, id, props);

    const account = props.env?.account || "";
    const region = props.env?.region || "";

    const api = new appsync.GraphqlApi(this, "AaaApi", {
      name: "AaaApi",
      xrayEnabled: true,
    });

    const mockQuery = new appsync.ResolvableField({
      returnType: appsync.GraphqlType.string(),
      dataSource: api.addNoneDataSource("none"),
      requestMappingTemplate: appsync.MappingTemplate.dynamoDbScanTable(),
      responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultList(),
    });
    api.addQuery("mockQuery", mockQuery);

    // Matching Calling Recording Stack

    const { SQSSqs } = props;

    const sqsDs = api.addHttpDataSource(
      "SqsDs",
      `https://sqs.${region}.amazonaws.com/`
    );

    const requestMappingTemplate = fs
      .readFileSync(
        join(
          __dirname,
          "/resolvers/sqs/sendSqs/request.vtl"
        ),
        {
          encoding: "utf-8",
        }
      )
      .replace("ACCOUNT_ID", account)
      .replace("QUEUE_NAME", SQSSqs.queueName);

    const sendSqs = new appsync.ResolvableField({
      returnType: appsync.GraphqlType.string(),
      dataSource: sqsDs,
      requestMappingTemplate: appsync.MappingTemplate.fromString(
        requestMappingTemplate
      ),
      responseMappingTemplate: appsync.MappingTemplate.fromFile(
        join(
          __dirname,
          "/resolvers/sqs/sendSqs/response.vtl"
        )
      ),
    });

    api.addMutation("sendSqsStudentRequest", sendSqs);
    // const role = new iam.Role(stack, 'Role', {
    //   assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
    // });
    // api.grant(role, appsync.IamResource.custom('types/Mutation/fields/updateExample'), 'appsync:GraphQL')
  }
}

SQS stack

import * as cdk from "@aws-cdk/core";
import * as node from "@aws-cdk/aws-lambda-nodejs";
import * as appsync from "@aws-cdk/aws-appsync";
import * as sqs from "@aws-cdk/aws-sqs";
import { ResolvableField } from "@aws-cdk/aws-appsync";
import * as fs from "fs";
import { join } from "path";

export class SQSStack extends cdk.Stack {
  readonly studentQueue: sqs.IQueue;

  constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    this.studentQueue = new sqs.Queue(this, "StudentQueue");
  }
}

What did you expect to happen?

CDK should have handled the routing and make sure that the appropriate resources (e.g. StudentQueue68D52AA1) was exported correctly

What actually happened?

The appropriate resource was not exported from SQS-stack

Environment

  • CDK CLI Version : 1.87.1
  • Framework Version:
  • Node.js Version: v14.15.4
  • OS : 10.15.7 (19H114)
  • Language (Version): TypeScript 3.9.7

Other

This issue might be similar https://github.com/aws/aws-cdk/issues/3619

Synth SQS stack

Resources:
  StudentQueue68D52AA1:
    Type: AWS::SQS::Queue
    Metadata:
      aws:cdk:path: AaaSQSStack/StudentQueue/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.87.1,@aws-cdk/aws-appsync=1.87.1,@aws-cdk/aws-cloudwatch=1.87.1,@aws-cdk/aws-iam=1.87.1,@aws-cdk/aws-kms=1.87.1,@aws-cdk/aws-sqs=1.87.1,@aws-cdk/cloud-assembly-schema=1.87.1,@aws-cdk/core=1.87.1,@aws-cdk/cx-api=1.87.1,@aws-cdk/region-info=1.87.1,jsii-runtime=node.js/v14.15.4
    Metadata:
      aws:cdk:path: AaaSQSStack/CDKMetadata/Default

Synth API stack

Resources:
  AaaApi72C55F6E:
    Type: AWS::AppSync::GraphQLApi
    Properties:
      AuthenticationType: API_KEY
      Name: AaaApi
      XrayEnabled: true
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/Resource
  AaaApiSchema7879F737:
    Type: AWS::AppSync::GraphQLSchema
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
      Definition: >
        schema {
          query: Query
          mutation: Mutation
        }

        type Query {
          mockQuery: String
        }

        type Mutation {
          sendSqsStudentRequest: String
        }
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/Schema
  AaaApiDefaultApiKeyDF40679C:
    Type: AWS::AppSync::ApiKey
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
    DependsOn:
      - AaaApiSchema7879F737
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/DefaultApiKey
  AaaApinone4B86ED1B:
    Type: AWS::AppSync::DataSource
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
      Name: none
      Type: NONE
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/none/Resource
  AaaApiSqsDsServiceRole12FDDD19:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: appsync.amazonaws.com
        Version: "2012-10-17"
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/SqsDs/ServiceRole/Resource
  AaaApiSqsDs580AB52D:
    Type: AWS::AppSync::DataSource
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
      Name: SqsDs
      Type: HTTP
      HttpConfig:
        Endpoint: https://sqs.us-east-1.amazonaws.com/
      ServiceRoleArn:
        Fn::GetAtt:
          - AaaApiSqsDsServiceRole12FDDD19
          - Arn
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/SqsDs/Resource
  AaaApiQuerymockQueryResolver3471C8E8:
    Type: AWS::AppSync::Resolver
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
      FieldName: mockQuery
      TypeName: Query
      DataSourceName: none
      Kind: UNIT
      RequestMappingTemplate: '{"version" : "2017-02-28", "operation" : "Scan"}'
      ResponseMappingTemplate: $util.toJson($ctx.result.items)
    DependsOn:
      - AaaApinone4B86ED1B
      - AaaApiSchema7879F737
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/QuerymockQueryResolver/Resource
  AaaApiMutationsendSqsStudentRequestResolver9F64A029:
    Type: AWS::AppSync::Resolver
    Properties:
      ApiId:
        Fn::GetAtt:
          - AaaApi72C55F6E
          - ApiId
      FieldName: sendSqsStudentRequest
      TypeName: Mutation
      DataSourceName: SqsDs
      Kind: UNIT
      RequestMappingTemplate:
        Fn::Join:
          - ""
          - - >-
              {
                "version": "2018-05-29",
                "method": "GET",
                "resourcePath": "/446416672052/
            - Fn::GetAtt:
                - StudentQueue68D52AA1
                - QueueName
            - >-
              ",
                "params": {
                  "query": {
                    "Action": "SendMessage",
                    "Version": "2012-11-05",
                    "MessageBody": "$util.urlEncode($util.toJson($ctx.args.input))"
                  }
                }
              }
      ResponseMappingTemplate: >-
        #set( $result = $utils.xml.toMap($ctx.result.body) )

        {
          "id": "$result.SendMessageResponse.SendMessageResult.MessageId",
          "email": "$ctx.args.input.email",
          "message": "$ctx.args.input.message",
        }
    DependsOn:
      - AaaApiSchema7879F737
      - AaaApiSqsDs580AB52D
    Metadata:
      aws:cdk:path: AaaApiStack/AaaApi/MutationsendSqsStudentRequestResolver/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.87.1,@aws-cdk/aws-appsync=1.87.1,@aws-cdk/aws-cloudwatch=1.87.1,@aws-cdk/aws-iam=1.87.1,@aws-cdk/aws-kms=1.87.1,@aws-cdk/aws-sqs=1.87.1,@aws-cdk/cloud-assembly-schema=1.87.1,@aws-cdk/core=1.87.1,@aws-cdk/cx-api=1.87.1,@aws-cdk/region-info=1.87.1,jsii-runtime=node.js/v14.15.4
    Metadata:
      aws:cdk:path: AaaApiStack/CDKMetadata/Default

This is 🐛 Bug Report

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
ruggero-baltericommented, Feb 1, 2021

found the problem. In API-stack import the property Queue from SQS-stack and I use it inside the .replace() function (not inside a cdk construct). Cdk, which should be in charge or creating the “wiring” between stacks, ignores the properties that are not used inside stacks, including the IQueue. As a workaround, I just instantiated the following resource (which I am not using) to setup the wiring.

    new cdk.CfnOutput(this, "WorkaroundForWiring", {
      value: SqsSqs.queueName,
    });

Since CfnOutput is a construct, the queueName is now exported from SQS stack and imported in API stack and can be use.

Why is this workaround necessary? Shouldn’t cdk take care of this situations without the need of a component?

1reaction
MrArnoldPalmercommented, Feb 16, 2021

@ruggero-balteri you’re right it should. This is likely a bug in appsync.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Template error: instance of Fn::GetAtt references undefined ...
I think you have to add the logical name of resource. Replace EventHandlerLambdaFunction to actual resource name eventHandler .
Read more >
Fn::GetAtt - AWS CloudFormation
The name of the resource-specific attribute whose value you want. See the resource's reference page for details about the attributes available for that...
Read more >
awslabs/aws-cdk - Gitter
@mjburling Its bundling up the resources with the lambda handler. ... /aws-cdk-how-do-i-reference-cross-stack-resources-in-same-app/61580038#61580038.
Read more >
Fn::GetAtt - Amazon CloudFormation - 亚马逊云科技
See the resource's reference page for details about the attributes available for that resource type. Return value. The attribute value. Examples. Return a ......
Read more >
Template error: instance of Fn::GetAtt references undefined ...
... the following error: Error: The CloudFormation template is invalid: Template error: instance of Fn::GetAtt references undefined resource…
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found