diff --git a/.changeset/ninety-coins-jog.md b/.changeset/ninety-coins-jog.md
new file mode 100644
index 00000000000..af73fe643e1
--- /dev/null
+++ b/.changeset/ninety-coins-jog.md
@@ -0,0 +1,7 @@
+---
+'@aws-amplify/deployed-backend-client': patch
+'@aws-amplify/client-config': patch
+'@aws-amplify/backend-cli': patch
+---
+
+Add error mapping for app name not available in the region
diff --git a/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.test.ts b/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.test.ts
index 004d94a2670..e09c76036fc 100644
--- a/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.test.ts
+++ b/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.test.ts
@@ -1,7 +1,10 @@
import { beforeEach, describe, it, mock } from 'node:test';
import { GenerateGraphqlClientCodeCommand } from './generate_graphql_client_code_command.js';
import yargs, { CommandModule } from 'yargs';
-import { TestCommandRunner } from '../../../test-utils/command_runner.js';
+import {
+ TestCommandError,
+ TestCommandRunner,
+} from '../../../test-utils/command_runner.js';
import assert from 'node:assert';
import { BackendIdentifier } from '@aws-amplify/plugin-types';
import path from 'path';
@@ -18,6 +21,10 @@ import { BackendIdentifierResolverWithFallback } from '../../../backend-identifi
import { S3Client } from '@aws-sdk/client-s3';
import { AmplifyClient } from '@aws-sdk/client-amplify';
import { CloudFormationClient } from '@aws-sdk/client-cloudformation';
+import {
+ BackendOutputClientError,
+ BackendOutputClientErrorType,
+} from '@aws-amplify/deployed-backend-client';
void describe('generate graphql-client-code command', () => {
const generateApiCodeAdapter = new GenerateApiCodeAdapter({
@@ -355,4 +362,45 @@ void describe('generate graphql-client-code command', () => {
);
assert.match(output, /Arguments .* are mutually exclusive/);
});
+
+ void it('throws user error when NO_APP_FOUND_ERROR occurs', async () => {
+ mock.method(generateApiCodeAdapter, 'invokeGenerateApiCode', () => {
+ throw new BackendOutputClientError(
+ BackendOutputClientErrorType.NO_APP_FOUND_ERROR,
+ 'No app found for stack stack_name'
+ );
+ });
+
+ await assert.rejects(
+ () =>
+ commandRunner.runCommand(
+ 'graphql-client-code --app-id test-app --branch main'
+ ),
+ (error: TestCommandError) => {
+ assert.strictEqual(error.error.name, 'AmplifyAppNotFoundError');
+ assert.strictEqual(
+ error.error.message,
+ 'No app found for stack stack_name'
+ );
+ return true;
+ }
+ );
+ });
+
+ void it('re-throw other types of errors', async () => {
+ const originalError = new Error('Some other error');
+ mock.method(generateApiCodeAdapter, 'invokeGenerateApiCode', () => {
+ throw originalError;
+ });
+ await assert.rejects(
+ () =>
+ commandRunner.runCommand(
+ 'graphql-client-code --app-id test-app --branch main'
+ ),
+ (error: TestCommandError) => {
+ assert.strictEqual(error.error, originalError);
+ return true;
+ }
+ );
+ });
});
diff --git a/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.ts b/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.ts
index ec8e4a6ed7e..40620b9eded 100644
--- a/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.ts
+++ b/packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.ts
@@ -15,6 +15,11 @@ import {
GenerateModelsOptions,
} from '@aws-amplify/model-generator';
import { ArgumentsKebabCase } from '../../../kebab_case.js';
+import { AmplifyUserError } from '@aws-amplify/platform-core';
+import {
+ BackendOutputClientError,
+ BackendOutputClientErrorType,
+} from '@aws-amplify/deployed-backend-client';
type GenerateOptions =
| GenerateGraphqlCodegenOptions
@@ -89,20 +94,38 @@ export class GenerateGraphqlClientCodeCommand
handler = async (
args: ArgumentsCamelCase
): Promise => {
- const backendIdentifier =
- await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
- args
- );
- const out = this.getOutDir(args);
- const format = args.format ?? GenerateApiCodeFormat.GRAPHQL_CODEGEN;
- const formatParams = this.formatParamBuilders[format](args);
+ try {
+ const backendIdentifier =
+ await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
+ args
+ );
+ const out = this.getOutDir(args);
+ const format = args.format ?? GenerateApiCodeFormat.GRAPHQL_CODEGEN;
+ const formatParams = this.formatParamBuilders[format](args);
- const result = await this.generateApiCodeAdapter.invokeGenerateApiCode({
- ...backendIdentifier,
- ...formatParams,
- } as unknown as InvokeGenerateApiCodeProps);
+ const result = await this.generateApiCodeAdapter.invokeGenerateApiCode({
+ ...backendIdentifier,
+ ...formatParams,
+ } as unknown as InvokeGenerateApiCodeProps);
- await result.writeToDirectory(out);
+ await result.writeToDirectory(out);
+ } catch (error) {
+ if (
+ BackendOutputClientError.isBackendOutputClientError(error) &&
+ error.code === BackendOutputClientErrorType.NO_APP_FOUND_ERROR
+ ) {
+ throw new AmplifyUserError(
+ 'AmplifyAppNotFoundError',
+ {
+ message: error.message,
+ resolution: `Ensure that an Amplify app exists in the region.`,
+ },
+ error
+ );
+ }
+ // Re-throw any other errors
+ throw error;
+ }
};
/**
diff --git a/packages/cli/src/commands/generate/outputs/generate_outputs_command.test.ts b/packages/cli/src/commands/generate/outputs/generate_outputs_command.test.ts
index 84b4a0f8e6c..462f0773128 100644
--- a/packages/cli/src/commands/generate/outputs/generate_outputs_command.test.ts
+++ b/packages/cli/src/commands/generate/outputs/generate_outputs_command.test.ts
@@ -2,7 +2,10 @@ import { beforeEach, describe, it, mock } from 'node:test';
import { GenerateOutputsCommand } from './generate_outputs_command.js';
import { ClientConfigFormat } from '@aws-amplify/client-config';
import yargs, { CommandModule } from 'yargs';
-import { TestCommandRunner } from '../../../test-utils/command_runner.js';
+import {
+ TestCommandError,
+ TestCommandRunner,
+} from '../../../test-utils/command_runner.js';
import assert from 'node:assert';
import { AppBackendIdentifierResolver } from '../../../backend-identifier/backend_identifier_resolver.js';
import { ClientConfigGeneratorAdapter } from '../../../client-config/client_config_generator_adapter.js';
@@ -11,6 +14,10 @@ import { SandboxBackendIdResolver } from '../../sandbox/sandbox_id_resolver.js';
import { S3Client } from '@aws-sdk/client-s3';
import { AmplifyClient } from '@aws-sdk/client-amplify';
import { CloudFormationClient } from '@aws-sdk/client-cloudformation';
+import {
+ BackendOutputClientError,
+ BackendOutputClientErrorType,
+} from '@aws-amplify/deployed-backend-client';
void describe('generate outputs command', () => {
const clientConfigGeneratorAdapter = new ClientConfigGeneratorAdapter({
@@ -248,4 +255,47 @@ void describe('generate outputs command', () => {
);
assert.match(output, /Arguments .* mutually exclusive/);
});
+
+ void it('throws user error when NO_APP_FOUND_ERROR occurs', async () => {
+ // Mock the generator to throw NO_APP_FOUND_ERROR
+ mock.method(
+ clientConfigGeneratorAdapter,
+ 'generateClientConfigToFile',
+ () => {
+ throw new BackendOutputClientError(
+ BackendOutputClientErrorType.NO_APP_FOUND_ERROR,
+ 'No Amplify app found in the specified region'
+ );
+ }
+ );
+
+ await assert.rejects(
+ () => commandRunner.runCommand('outputs --app-id test-app --branch main'),
+ (error: TestCommandError) => {
+ assert.strictEqual(error.error.name, 'AmplifyAppNotFoundError');
+ assert.strictEqual(
+ error.error.message,
+ 'No Amplify app found in the specified region'
+ );
+ return true;
+ }
+ );
+ });
+ void it('re-throw other types of errors', async () => {
+ const originalError = new Error('Some other error');
+ mock.method(
+ clientConfigGeneratorAdapter,
+ 'generateClientConfigToFile',
+ () => {
+ throw originalError;
+ }
+ );
+ await assert.rejects(
+ () => commandRunner.runCommand('outputs --app-id test-app --branch main'),
+ (error: TestCommandError) => {
+ assert.strictEqual(error.error, originalError);
+ return true;
+ }
+ );
+ });
});
diff --git a/packages/cli/src/commands/generate/outputs/generate_outputs_command.ts b/packages/cli/src/commands/generate/outputs/generate_outputs_command.ts
index 0edb427a00e..e71afddf289 100644
--- a/packages/cli/src/commands/generate/outputs/generate_outputs_command.ts
+++ b/packages/cli/src/commands/generate/outputs/generate_outputs_command.ts
@@ -9,6 +9,10 @@ import { BackendIdentifierResolver } from '../../../backend-identifier/backend_i
import { ClientConfigGeneratorAdapter } from '../../../client-config/client_config_generator_adapter.js';
import { ArgumentsKebabCase } from '../../../kebab_case.js';
import { AmplifyUserError } from '@aws-amplify/platform-core';
+import {
+ BackendOutputClientError,
+ BackendOutputClientErrorType,
+} from '@aws-amplify/deployed-backend-client';
export type GenerateOutputsCommandOptions =
ArgumentsKebabCase;
@@ -55,25 +59,43 @@ export class GenerateOutputsCommand
handler = async (
args: ArgumentsCamelCase
): Promise => {
- const backendIdentifier =
- await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
- args
- );
+ try {
+ const backendIdentifier =
+ await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
+ args
+ );
- if (!backendIdentifier) {
- throw new AmplifyUserError('BackendIdentifierResolverError', {
- message: 'Could not resolve the backend identifier.',
- resolution:
- 'Ensure stack name or Amplify App ID and branch specified are correct and exists, then re-run this command.',
- });
- }
+ if (!backendIdentifier) {
+ throw new AmplifyUserError('BackendIdentifierResolverError', {
+ message: 'Could not resolve the backend identifier.',
+ resolution:
+ 'Ensure stack name or Amplify App ID and branch specified are correct and exists, then re-run this command.',
+ });
+ }
- await this.clientConfigGenerator.generateClientConfigToFile(
- backendIdentifier,
- args.outputsVersion as ClientConfigVersion,
- args.outDir,
- args.format
- );
+ await this.clientConfigGenerator.generateClientConfigToFile(
+ backendIdentifier,
+ args.outputsVersion as ClientConfigVersion,
+ args.outDir,
+ args.format
+ );
+ } catch (error) {
+ if (
+ BackendOutputClientError.isBackendOutputClientError(error) &&
+ error.code === BackendOutputClientErrorType.NO_APP_FOUND_ERROR
+ ) {
+ throw new AmplifyUserError(
+ 'AmplifyAppNotFoundError',
+ {
+ message: error.message,
+ resolution: `Ensure that an Amplify app exists in the region.`,
+ },
+ error
+ );
+ }
+ // Re-throw any other errors
+ throw error;
+ }
};
/**
diff --git a/packages/client-config/src/unified_client_config_generator.ts b/packages/client-config/src/unified_client_config_generator.ts
index 068b2c03493..cf771a7dfe3 100644
--- a/packages/client-config/src/unified_client_config_generator.ts
+++ b/packages/client-config/src/unified_client_config_generator.ts
@@ -103,6 +103,15 @@ export class UnifiedClientConfigGenerator implements ClientConfigGenerator {
},
error
);
+ case BackendOutputClientErrorType.NO_APP_FOUND_ERROR:
+ throw new AmplifyUserError(
+ 'AmplifyAppNotFoundError',
+ {
+ message: error.message,
+ resolution: `Ensure that an Amplify app exists in the region.`,
+ },
+ error
+ );
}
}
throw error;
diff --git a/packages/deployed-backend-client/API.md b/packages/deployed-backend-client/API.md
index 3c5353103ac..af522a516c5 100644
--- a/packages/deployed-backend-client/API.md
+++ b/packages/deployed-backend-client/API.md
@@ -103,6 +103,8 @@ export enum BackendOutputClientErrorType {
// (undocumented)
METADATA_RETRIEVAL_ERROR = "MetadataRetrievalError",
// (undocumented)
+ NO_APP_FOUND_ERROR = "NoAppFoundError",
+ // (undocumented)
NO_OUTPUTS_FOUND = "NoOutputsFound",
// (undocumented)
NO_STACK_FOUND = "NoStackFound"
diff --git a/packages/deployed-backend-client/src/backend_output_client_factory.ts b/packages/deployed-backend-client/src/backend_output_client_factory.ts
index f9e553f369d..6220d1e472c 100644
--- a/packages/deployed-backend-client/src/backend_output_client_factory.ts
+++ b/packages/deployed-backend-client/src/backend_output_client_factory.ts
@@ -13,6 +13,7 @@ export enum BackendOutputClientErrorType {
NO_STACK_FOUND = 'NoStackFound',
CREDENTIALS_ERROR = 'CredentialsError',
ACCESS_DENIED = 'AccessDenied',
+ NO_APP_FOUND_ERROR = 'NoAppFoundError',
}
/**
* Error type for BackendOutputClientError