pulumi: TypeError: Cannot read property 'length' of undefined at getAvailabilityZones

A stack I’ve been working with has stopped working for preview and up for me.

This code:

import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

const provider = new aws.Provider(
    "my-provider",
    {
        sharedCredentialsFile: "~/.aws/sandbox-credentials"
    });

const myVpc = new awsx.ec2.Vpc("my-vpc", {
    subnets: [
        {type: "public"},
        {type: "private"},
    ],
    numberOfNatGateways: 1,
}, { provider });

pulumi preview results in:

Previewing update (dev):

     Type                     Name                Plan       Info
     pulumi:pulumi:Stack      aws-typescript-dev             1 error
 +   ├─ awsx:x:ec2:Vpc        my-vpc              create
 +   └─ pulumi:providers:aws  sandbox-provider    create
 
Diagnostics:
  pulumi:pulumi:Stack (aws-typescript-dev):
    error: Running program 'D:\dev\damianh\pulumi-vpc\src' failed with an unhandled exception:
    TypeError: Cannot read property 'length' of undefined
        at getAvailabilityZones (D:\dev\damianh\pulumi-vpc\src\node_modules\@pulumi\ec2\vpc.ts:302:22)
        at new Vpc (D:\dev\damianh\pulumi-vpc\src\node_modules\@pulumi\ec2\vpc.ts:63:39)
        at Object.<anonymous> (D:\dev\damianh\pulumi-vpc\src\index.ts:12:15)
        at Module._compile (internal/modules/cjs/loader.js:955:30)
        at Module.m._compile (D:\dev\damianh\pulumi-vpc\src\node_modules\ts-node\src\index.ts:814:23)
        at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
        at Object.require.extensions.<computed> [as .ts] (D:\dev\damianh\pulumi-vpc\src\node_modules\ts-node\src\index.ts:817:12)
        at Module.load (internal/modules/cjs/loader.js:811:32)
        at Function.Module._load (internal/modules/cjs/loader.js:723:14)
        at Module.require (internal/modules/cjs/loader.js:848:19)

Node version: v12.14.1 Pulumi version: v1.8.1

I had to set this to prevent the hanging issue: pulumi:noSyncCalls: "true"

I’ve posted a repro project to https://github.com/damianh/pulumi-vpc I’ve validated this with a colleague.

I’m dead in the water with this 😦

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (9 by maintainers)

Most upvoted comments

@seivan Hooboy, it’s long and complex to explain. Here’s the best way i can sum it up.

When you pass { provider } to a resource, we end up using it to inform queries we make (like getAvailabilityZones). i.e. we’re using that provider to answer the question what region are you asking for availability zones in?.

This currently has some significant problems because we end up making that call to getAvailabilityZones synchronously and we depend on a library to do that that ends up causing hangs and other issues for many users (across many versins of nodejs and OS).

To avoid this problem currently the use of await pulumi.ProviderResource.register(provider); allows us to avoid the codepath that goes through that problematic library. i.e. without that line, we end up calling problematiclibrary.uhoh(()=> ProviderResource.register(provider)).

By pulling this line of code out to a location that can be async, we side-step this issue until the full fix and updates to all our libraries are released.

Hi @damianh So i don’t have great news for you. The problem right now is the use of pulumi:noSyncCalls: "true" and this version of the library. They’re just not compatible together. TO move forward (until we release 0.18.15) you’ll need to remove pulumi:noSyncCalls: "true".

Now, as you mentioned, this gives you a hang. The path forward on that, unfortunately, is to take the approach specified here: https://www.pulumi.com/docs/troubleshooting/#register-the-provider-first

You’ll specifically have to do this:

const provider = new aws.Provider(
    "my-provider",
    {
        sharedCredentialsFile: "~/.aws/sandbox-credentials"
    });

// this line is new
await ProviderResource.register(provider);

const myVpc = new awsx.ec2.Vpc("my-vpc", {
    subnets: [
        {type: "public"},
        {type: "private"},
    ],
    numberOfNatGateways: 1,
}, { provider });

Note: because this uses await, you’ll need to use async/await. you could do this like so:

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

export = async () => {
    const provider = new aws.Provider(
        "my-provider",
        {
            sharedCredentialsFile: "~/.aws/sandbox-credentials",
            region: "us-east-2"
        });

    await pulumi.ProviderResource.register(provider);

    const myVpc = new awsx.ec2.Vpc("my-vpc", {
        subnets: [
            {type: "public"},
            {type: "private"},
        ],
        numberOfNatGateways: 1,
    }, { provider });
}

I have tested this out and validated that it works:

image