Skip to content
cdkd

Templates cdkd refuses

Before it calls AWS, cdkd checks the synthesized template. It refuses a template it could only deploy as something other than what the template declares. For every entry on this page the fix is in the CDK app. Only the unsupported-type refusal has a flag that overrides it.

On this page:

An unsupported resource type

The following resource types are not supported by cdkd:
  - AWS::AppMesh::Mesh
      AWS reports this type as NON_PROVISIONABLE (Cloud Control API cannot
      manage it) and cdkd has no SDK provider for it.
      Request support: https://github.com/go-to-k/cdkd/issues/new?title=...

To attempt deployment anyway (Cloud Control will likely fail for
NON_PROVISIONABLE types), re-run with: --allow-unsupported-types AWS::AppMesh::Mesh

A type that slips past pre-flight fails at provisioning time instead:

No provider available for resource type: AWS::CustomService::Resource. This
resource type is not supported by Cloud Control API and no SDK provider is
registered.

cdkd provisions a resource through one of its own SDK providers, or through the AWS Cloud Control API when it has no provider for the type. This error means neither is available, for one of three reasons:

  • AWS reports the type as NON_PROVISIONABLE, so Cloud Control cannot manage it.
  • cdkd blocks the type on Cloud Control until it has a dedicated provider.
  • The type is not an AWS:: type at all.

What you can do:

  • Request the type. The message carries a link that opens a pre-filled issue for exactly this type.

  • Deploy now, if the type is only blocked by cdkd.

    cdkd deploy MyStack --allow-unsupported-types AWS::AppMesh::Mesh
    

    The flag routes the named type through Cloud Control. It takes type names, so each one is an explicit choice. For a NON_PROVISIONABLE type Cloud Control cannot manage it either, and the deploy still fails.

  • Check coverage. Supported Resources lists cdkd's per-type coverage, and AWS lists what Cloud Control supports.

Deploy: safety & compatibility flags documents --allow-unsupported-types.

"The following resources declare mutually exclusive properties"

The following resources declare mutually exclusive properties:
  - BadRoute (AWS::EC2::Route) declares DestinationCidrBlock and DestinationIpv6CidrBlock
      CloudFormation and the EC2 CreateRoute API accept exactly one destination per route.
      cdkd would send only DestinationCidrBlock; DestinationIpv6CidrBlock would be dropped.
      Deleting the dropped keys changes nothing cdkd sends — but if the LIVE resource was
      created from one of them, making DestinationCidrBlock the sole value is a create-only
      change that REPLACES it.
      Declare at most one of: DestinationCidrBlock / DestinationIpv6CidrBlock / DestinationPrefixListId

The template declares two or more properties of which AWS accepts only one. CloudFormation rejects the same template, so no --allow-* flag overrides the refusal. cdkd runs the check on every deploy before any AWS call, including a deploy where the resource is unchanged.

cdkd diff reports no change for such a resource, but it warns that some of the declared properties cannot be sent as declared.

Remove every key except the one the message says cdkd would send:

new ec2.CfnRoute(this, 'Route', {
  routeTableId: rt.ref,
  gatewayId: igw.ref,
  destinationCidrBlock: '0.0.0.0/0',
  // delete this line; only one destination is allowed:
  // destinationIpv6CidrBlock: '::/0',
});

Warning

Check what the live resource was created from first. If it was created from one of the dropped keys, making a different key the sole value is a create-only change and replaces the resource.

If the resource needs a different property per environment, put each behind a condition whose other arm is AWS::NoValue. cdkd does not refuse a key behind an unresolved intrinsic, and exactly one of the two survives resolution:

{
  "DestinationCidrBlock": {
    "Fn::If": ["IsV4", "0.0.0.0/0", { "Ref": "AWS::NoValue" }]
  },
  "DestinationIpv6CidrBlock": {
    "Fn::If": ["IsV4", { "Ref": "AWS::NoValue" }, "::/0"]
  }
}

"The following resources declare a nested property block without a member it requires"

The following resources declare a nested property block without a member it requires:
  - Service (AWS::ECS::Service): DeploymentConfiguration.DeploymentCircuitBreaker is missing required member Rollback

The template contains a nested block that leaves out a member the resource type's schema requires in that block. If cdkd sent the block as written, the service might accept it and replace the live block with it, which resets the member that was left out. The block in the message above would switch a live rollback off.

Declare the missing members:

new ecs.CfnService(this, 'Service', {
  // ...
  deploymentConfiguration: {
    deploymentCircuitBreaker: { enable: true, rollback: true },
  },
});

cdkd runs the check on every deploy before any AWS call. CloudFormation refuses the same template, so no --allow-* flag overrides the refusal.

What the nested-block check does not refuse

  • An absent block is never refused, only a present and incomplete one.
  • A block, element or member behind an unresolved intrinsic (Fn::If, Ref) is not refused.
  • The check covers the resource types CloudFormation enforces these lists on.
  • Array elements are named by index (Policies[1]).

"Properties validation failed": a list where an object is expected, or the reverse

Properties validation failed: the following resources declare a property whose kind contradicts the resource type's schema:
  - Queue (AWS::SQS::Queue): #/Tags: expected type: JSONArray, found: JSONObject

A template property is an object where the schema requires a list, or a list where it requires an object. The usual source is an addPropertyOverride that wrote the wrong kind. Give the property the kind the schema declares:

(queue.node.defaultChild as sqs.CfnQueue).addPropertyOverride('Tags', [
  { Key: 'team', Value: 'platform' }, // a list, not { Key, Value }
]);

cdkd runs the check on every deploy before any AWS call. CloudFormation refuses the same template with the same words, so no --allow-* flag overrides the refusal.

What the kind check does not refuse

  • Only a list against an object is refused. A scalar mismatch is left to CloudFormation's and the service's own checks.
  • A property is checked only where the schema admits exactly one of the two kinds.
  • A value that is an unresolved intrinsic (Ref, Fn::If, Fn::Split) is not refused.
  • Array elements are named by index (Tags[1]).

"The following custom resources pass a secure dynamic reference"

The following custom resources pass a secure dynamic reference ({{resolve:secretsmanager:...}} / {{resolve:ssm-secure:...}}) in their properties:
  - DbInit: Password

A custom resource (Custom::* or AWS::CloudFormation::CustomResource) has a property holding a {{resolve:secretsmanager:...}} or {{resolve:ssm-secure:...}} reference, directly or inside an intrinsic. CloudFormation does not support secure dynamic references in custom resources. cdkd refuses before resolving anything, so the secret never reaches the handler's event.

  • Pass the secret's name or ARN instead, and have the handler read the value (grant its role secretsmanager:GetSecretValue or ssm:GetParameter).
  • For a value that is not secret, use a plain {{resolve:ssm:...}} parameter.

The check runs on every deploy, including one where the resource is unchanged, and no --allow-* flag overrides it. cdkd destroy does not run the check, so a stack that already carries such a resource can still be torn down.

A plain {{resolve:ssm:...}} reference that names a SecureString parameter passes this check. cdkd refuses it later, when the handler would be invoked: see "Custom resource X: Y resolved to the value of a secret".

"OpenTableFormatInput.IcebergInput.IcebergTableInput cannot be deployed" on a Glue table

AWS::Glue::Table IcebergTable: OpenTableFormatInput.IcebergInput.IcebergTableInput
cannot be deployed by AWS in any shape, so cdkd refuses it before calling Glue
(issue #1454).

AWS accepts no shape of this property: glue:CreateTable rejects it, and CloudFormation rolls the same template back. cdkd refuses a create that declares it, before calling Glue.

Move the table metadata into TableInput and leave IcebergInput carrying only the create-time directive:

TableInput:
  Name: events_iceberg
  TableType: EXTERNAL_TABLE          # required for Iceberg
  StorageDescriptor:
    Location: s3://your-bucket/iceberg/events/
    Columns:
      - Name: event_id
        Type: string
OpenTableFormatInput:
  IcebergInput:
    MetadataOperation: CREATE        # Version: '2' is also accepted

Glue writes the Iceberg metadata itself. The created table comes back with Parameters.table_type = ICEBERG and a populated Parameters.metadata_location.

When cdkd warns about IcebergTableInput and does not refuse

  • An update. Adding IcebergTableInput to a table that is already deployed produces a warning and a successful deploy. cdkd sends nothing for the property, so it is ignored.
  • A cdkd rollback. A rollback re-applies what cdkd recorded in state and does not read your template, so you could not fix a refusal there.

See "Glue table Iceberg support" in Supported Resources for the background.

"SelfManagedKafkaEventSourceConfig.ConsumptionMode cannot be sent by cdkd yet"

AWS::Lambda::EventSourceMapping MyMapping: SelfManagedKafkaEventSourceConfig.ConsumptionMode
cannot be sent by cdkd yet — the AWS SDK for JavaScript does not model the member, so it
would be dropped from the CreateEventSourceMapping request without an error (issue #3848).
Remove ConsumptionMode from SelfManagedKafkaEventSourceConfig to deploy the mapping without it.

The CloudFormation schema declares ConsumptionMode (Stream or Queue) on a self-managed Kafka event source mapping, but the AWS SDK cdkd calls Lambda through drops it from the request. cdkd refuses a create that declares it, and an update that adds or changes it, rather than deploy a mapping without the mode you asked for.

Remove ConsumptionMode from SelfManagedKafkaEventSourceConfig.

Sending the resource through the Cloud Control API does not help, because Lambda rejects the member there too (Unsupported 'ConsumptionMode' parameter for given event source mapping type). A cdkd rollback or cdkd drift --revert only warns, because those commands re-apply a recorded configuration.

  • Troubleshooting: the common problems and the list of every troubleshooting page

Last updated: