aws-amplify / amplify-backend

Home to all tools related to Amplify's code-first DX (Gen 2) for building fullstack apps on AWS
Apache License 2.0
175 stars 60 forks source link

Sandbox failing after adding post-confirmation lambda according to documentation #1666

Closed Carlos-Butler closed 4 months ago

Carlos-Butler commented 4 months ago

Environment information

System:
  OS: Windows 11 10.0.22631
  CPU: (12) x64 12th Gen Intel(R) Core(TM) i7-1265U
  Memory: 2.62 GB / 15.69 GB
Binaries:
  Node: 20.10.0 - C:\Program Files (x86)\Nodist\bin\node.EXE
  Yarn: undefined - undefined
  npm: 10.2.3 - C:\Program Files (x86)\Nodist\bin\npm.EXE
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 1.0.3
  @aws-amplify/backend-cli: 1.0.4
  aws-amplify: 6.3.6
  aws-cdk: 2.146.0
  aws-cdk-lib: 2.146.0
  typescript: 5.4.5
AWS environment variables:
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
  AWS_STS_REGIONAL_ENDPOINTS = regional
No CDK environment variables

Description

After loading a basic amplify backend using "npm create amplify@latest" and running "npx ampx sandbox", I tried to add a post-confirmation lambda according to the gen 2 documentation here https://docs.amplify.aws/javascript/build-a-backend/functions/examples/add-user-to-group/

This results in the error: Failed to instantiate nodejs function construct Caused By: Failed to bundle asset

It additionally gives me the info: Error: cmd /c npx.cmd --no-install esbuild --bundle

Strangely enough, it seems to break all other lambda functions as well. I tested this by making a fresh amplify backend containing the basic say-hello lambda from the docu, which works in the sandbox. After adding the post-confirmation lambda, the sandbox fails. Disabling the post-confirmation lambda again leads to the same error occuring on the say-hello lambda, which previously worked.

I'd be grateful for any help.

ykethan commented 4 months ago

Hey @Carlos-Butler, thank you for reaching out. Could you try adding the --debug to the sandbox command and provide us the output from the terminal.

Carlos-Butler commented 4 months ago

Thanks for your reply, here is the output from the terminal:

[DEBUG] 2024-06-19T06:17:32.245Z: [Sandbox] Executing command deploy
[DEBUG] 2024-06-19T06:18:02.161Z: Bundling asset amplify-leaviosabackend-cbutler-sandbox-f3569d40d8/function/post-confirmation-lambda/Code/Stage...

[DEBUG] 2024-06-19T06:18:03.152Z: 'npx.cmd' is not recognized as an internal or external command,
operable program or batch file.

[DEBUG] 2024-06-19T06:18:03.173Z: C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\src\factory.ts:316
      throw new AmplifyUserError(
            ^

AmplifyError [NodeJSFunctionConstructInitializationError]: Failed to instantiate nodejs function construct
    at AmplifyFunction (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\src\factory.ts:316:13)
    at FunctionGenerator.generateContainerEntry (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\src\factory.ts:239:12)
    at SingletonConstructContainer.getOrCompute (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend\src\engine\singleton_construct_container.ts:51:19)
    at FunctionFactory.getInstance (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\src\factory.ts:119:31)
    at <anonymous> (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-auth\src\factory.ts:166:26)
    at Array.forEach (<anonymous>)
    at AmplifyAuthGenerator.generateContainerEntry (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-auth\src\factory.ts:162:47)
    at SingletonConstructContainer.getOrCompute (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend\src\engine\singleton_construct_container.ts:51:19)
    at AmplifyAuthFactory.getInstance (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-auth\src\factory.ts:110:31)
    at <anonymous> (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend\src\backend_factory.ts:115:68) {
  cause: Error: Failed to bundle asset amplify-leaviosabackend-cbutler-sandbox-f3569d40d8/function/post-confirmation-lambda/Code/Stage, bundle output is located at C:\Users\c.butler\Projects\leaviosa-backend\.amplify\artifacts\cdk.out\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d-error: Error: cmd /c npx.cmd --no-install esbuild --bundle "C:\Users\c.butler\Projects\leaviosa-backend\amplify\auth\post-confirmation\handler.ts" --target=node18 --platform=node --format=esm --outfile="C:\Users\c.butler\Projects\leaviosa-backend\.amplify\artifacts\cdk.out\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d\index.mjs" --external:@aws-sdk/* --loader:.node=file --banner:js="/** * Reads SSM environment context from a known Amplify environment variable, * fetches values from SSM and places those values in the corresponding environment variables */export const internalAmplifyFunctionResolveSsmParams = async (client) => {    const envPathObject = JSON.parse(process.env.AMPLIFY_SSM_ENV_CONFIG ?? '{}');    const paths = Object.keys(envPathObject);    if (paths.length === 0) {        return;    }    let actualSsmClient;    if (client) {        actualSsmClient = client;    }    else {        const ssmSdk = await import('@aws-sdk/client-ssm');        actualSsmClient = new ssmSdk.SSM();    }    const resolveSecrets = async (paths) => {        const response = await actualSsmClient.getParameters({            Names: paths,            WithDecryption: true,        });        if (response.Parameters && response.Parameters.length > 0) {            for (const parameter of response.Parameters) {                if (parameter.Name) {                    const envKey = Object.keys(envPathObject).find((key) => envPathObject[key].sharedPath === parameter.Name);                    const envName = envKey                        ? envPathObject[envKey].name                        : envPathObject[parameter.Name]?.name;                    process.env[envName] = parameter.Value;                }            }        }        return response;    };    const response = await resolveSecrets(paths);    const sharedPaths = (response?.InvalidParameters || [])        .map((invalidParam) => envPathObject[invalidParam].sharedPath)        .filter((sharedParam) => !!sharedParam);     if (sharedPaths.length > 0) {        await resolveSecrets(sharedPaths);    }};await internalAmplifyFunctionResolveSsmParams();const SSM_PARAMETER_REFRESH_MS = 1000 * 60;setInterval(() => {    void internalAmplifyFunctionResolveSsmParams();}, SSM_PARAMETER_REFRESH_MS);export {};" --inject:"C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\lib\lambda-shims\cjs_shim.js" run in directory C:\Users\c.butler\Projects\leaviosa-backend exited with status 1        
      at AssetStaging.bundle (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\core\lib\asset-staging.js:2:619)
      at AssetStaging.stageByBundling (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\core\lib\asset-staging.js:1:5297)
      at stageThisAsset (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\core\lib\asset-staging.js:1:2728)
      at Cache.obtain (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\core\lib\private\cache.js:1:242)
      at new AssetStaging (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\core\lib\asset-staging.js:1:3125)
      at new Asset (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\aws-s3-assets\lib\asset.js:1:1141)
      at AssetCode.bind (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\aws-lambda\lib\code.js:5:3487)
      at new Function (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\aws-lambda\lib\function.js:1:9422)
      at new NodejsFunction (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\aws-cdk-lib\aws-lambda-nodejs\lib\function.js:1:2111)
      at AmplifyFunction (C:\Users\c.butler\Projects\leaviosa-backend\node_modules\@aws-amplify\backend-function\src\factory.ts:301:24),
  classification: 'ERROR',
  options: {
    message: 'Failed to instantiate nodejs function construct',
    resolution: 'See the underlying error message for more details.'
  },
  serializedError: `{"name":"NodeJSFunctionConstructInitializationError","classification":"ERROR","options":{"message":"Failed to instantiate nodejs function construct","resolution":"See the underlying error message for more details."},"cause":{"name":"Error","message":"Failed to bundle asset amplify-leaviosabackend-cbutler-sandbox-f3569d40d8/function/post-confirmation-lambda/Code/Stage, bundle output is located at C:\\\\Users\\\\c.butler\\\\Projects\\\\leaviosa-backend\\\\.amplify\\\\artifacts\\\\cdk.out\\\\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d-error: Error: cmd /c npx.cmd --no-install esbuild --bundle \\"C:\\\\Users\\\\c.butler\\\\Projects\\\\leaviosa-backend\\\\amplify\\\\auth\\\\post-confirmation\\\\handler.ts\\" --target=node18 --platform=node --format=esm --outfile=\\"C:\\\\Users\\\\c.butler\\\\Projects\\\\leaviosa-backend\\\\.amplify\\\\artifacts\\\\cdk.out\\\\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d\\\\index.mjs\\" --external:@aws-sdk/* --loader:.node=file --banner:js=\\"/** * Reads SSM environment context from a known Amplify environment variable, * fetches values from SSM and places those values in the corresponding environment variables */export const internalAmplifyFunctionResolveSsmParams = async (client) => {    const envPathObject = JSON.parse(process.env.AMPLIFY_SSM_ENV_CONFIG ?? '{}');    const paths = Object.keys(envPathObject);    if (paths.length === 0) {        return;    }    let actualSsmClient;    if (client) {        actualSsmClient = client;    }    else {        const ssmSdk = await import('@aws-sdk/client-ssm');        actualSsmClient = new ssmSdk.SSM();    }    const resolveSecrets = async (paths) => {        const response = await actualSsmClient.getParameters({            Names: paths,            WithDecryption: true,        });        if (response.Parameters && response.Parameters.length > 0) {            for (const parameter of response.Parameters) {                if (parameter.Name) {                    const envKey = Object.keys(envPathObject).find((key) => envPathObject[key].sharedPath === parameter.Name);                    const envName = envKey                       
 ? envPathObject[envKey].name                        : envPathObject[parameter.Name]?.name;                    process.env[envName] = parameter.Value;                }            }        }        return response;    };    const response = await resolveSecrets(paths);    const sharedPaths = (response?.InvalidParameters || [])        .map((invalidParam) => envPathObject[invalidParam].sharedPath)        .filter((sharedParam) => !!sharedParam);     if (sharedPaths.length > 0) {        await resolveSecrets(sharedPaths);    }};await internalAmplifyFunctionResolveSsmParams();const SSM_PARAMETER_REFRESH_MS = 1000 * 60;setInterval(() => {    void internalAmplifyFunctionResolveSsmParams();}, SSM_PARAMETER_REFRESH_MS);export {};\\" --inject:\\"C:\\\\Users\\\\c.butler\\\\Projects\\\\leaviosa-backend\\\\node_modules\\\\@aws-amplify\\\\backend-function\\\\lib\\\\lambda-shims\\\\cjs_shim.js\\" run in directory C:\\\\Users\\\\c.butler\\\\Projects\\\\leaviosa-backend exited with status 1"}}`,
  resolution: 'See the underlying error message for more details.',
  details: undefined,
  link: undefined,
  code: undefined
}

Node.js v20.10.0

[DEBUG] 2024-06-19T06:18:03.425Z: 

[DEBUG] 2024-06-19T06:18:03.426Z: Subprocess exited with error 1

[DEBUG] 2024-06-19T06:18:09.718Z: {
    "compilerOptions": {
        "target": "es2022",
        "module": "es2022",
        "moduleResolution": "bundler",
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "paths": {
            "$amplify/*": [
                "../.amplify/generated/*"
            ]
        },
        "allowSyntheticDefaultImports": true,
        "resolvePackageJsonExports": true,
        "resolvePackageJsonImports": true,
        "useDefineForClassFields": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "strictBindCallApply": true,
        "strictPropertyInitialization": true,
        "alwaysStrict": true,
        "useUnknownInCatchVariables": true
    },
    "files": [
        "./backend.ts",
        "./auth/resource.ts",
        "./auth/post-confirmation/handler.ts",
        "./auth/post-confirmation/resource.ts",
        "./data/resource.ts",
        "./functions/say-hello/handler.ts",
        "./functions/say-hello/resource.ts"
    ]
}

Failed to instantiate nodejs function construct
Caused By: Failed to bundle asset amplify-leaviosabackend-cbutler-sandbox-f3569d40d8/function/post-confirmation-lambda/Code/Stage, bundle output is located at C:\\Users\\c.butler\\Projects\\leaviosa-backend\\.amplify\\artifacts\\cdk.out\\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d-error: Error: cmd /c npx.cmd --no-install esbuild --bundle "C:\\Users\\c.butler\\Projects\\leaviosa-backend\\amplify\\auth\\post-confirmation\\handler.ts" --target=node18 --platform=node --format=esm --outfile="C:\\Users\\c.butler\\Projects\\leaviosa-backend\\.amplify\\artifacts\\cdk.out\\bundling-temp-905b3178164f526cfbbea4ba925d9d13b4a20f8411a32532c2d5c4ab4787078d\\index.mjs" --external:@aws-sdk/* --loader:.node=file --banner:js="/** * Reads SSM environment context from a known Amplify environment variable, * fetches values from SSM and places those values in the corresponding environment variables */export const internalAmplifyFunctionResolveSsmParams = async (client) => {    const envPathObject = JSON.parse(process.env.AMPLIFY_SSM_ENV_CONFIG ?? '{}');    const paths = Object.keys(envPathObject);    if (paths.length === 0) {        return;    }    let actualSsmClient;    if (client) {        actualSsmClient = client;    }    else {        const ssmSdk = await import('@aws-sdk/client-ssm');        actualSsmClient = new ssmSdk.SSM();    }    const resolveSecrets = async (paths) => {        const response = await actualSsmClient.getParameters({            Names: paths,            WithDecryption: true,        });        if (response.Parameters && response.Parameters.length > 0) {            for (const parameter of response.Parameters) {                if (parameter.Name) {                    const envKey = Object.keys(envPathObject).find((key) => envPathObject[key].sharedPath === parameter.Name);                    const envName = envKey                        ? envPathObject[envKey].name                        : envPathObject[parameter.Name]?.name;                    process.env[envName] = parameter.Value;                }            }        }        return response;    };    const response = await resolveSecrets(paths);    const sharedPaths = (response?.InvalidParameters || [])        .map((invalidParam) => envPathObject[invalidParam].sharedPath)        .filter((sharedParam) => !!sharedParam);     if (sharedPaths.length > 0) {        await resolveSecrets(sharedPaths);    }};await internalAmplifyFunctionResolveSsmParams();const SSM_PARAMETER_REFRESH_MS = 1000 * 60;setInterval(() => {    void internalAmplifyFunctionResolveSsmParams();}, SSM_PARAMETER_REFRESH_MS);export {};" --inject:"C:\\Users\\c.butler\\Projects\\leaviosa-backend\\node_modules\\@aws-amplify\\backend-function\\lib\\lambda-shims\\cjs_shim.js" run in directory C:\\Users\\c.butler\\Projects\\leaviosa-backend exited with status 1

Resolution: See the underlying error message for more details.

[INFO] 2024-06-19T06:18:30.265Z: [Sandbox] Watching for file changes...

In case it helps, I was able to successfully deploy the project in the amplify console.

Carlos-Butler commented 4 months ago

Update: I got it working again by changing my node js manager from Nodist to nvm for windows and reinstalling npm. I suspect the problem was linked to an error mentioned in the README of Nodist, which caused packages to get stuck in shim.