Skip to content

Commit 62bd951

Browse files
author
aws-amplify-bot
committed
Merge remote-tracking branch 'origin/main' into pre-prod/main
2 parents 55cc9bb + 229127d commit 62bd951

File tree

3 files changed

+51
-142
lines changed
  • src/pages/[platform]/build-a-backend
    • add-aws-services/rest-api/set-up-rest-api
    • data/connect-event-api
    • troubleshooting/cannot-find-module-amplify-env

3 files changed

+51
-142
lines changed

src/pages/[platform]/build-a-backend/add-aws-services/rest-api/set-up-rest-api/index.mdx

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ npm add aws-amplify @aws-amplify/react-native
204204
## Initialize Amplify API
205205

206206
<InlineFilter filters={['javascript', "angular", "react", "vue", "react-native", "nextjs"]}>
207+
208+
<Callout info="true">
209+
210+
**Important**: Custom REST APIs require explicit configuration. Unlike built-in Amplify resources (Auth, Data), custom APIs are not automatically included when calling `Amplify.configure(outputs)`.
211+
212+
</Callout>
213+
207214
To initialize the Amplify API category you need to configure Amplify with `Amplify.configure()`.
208215

209216
Import and load the configuration file in your app. It's recommended you add the Amplify configuration step to your app's root entry point. For example `index.js` in React or `main.ts` in Angular.
@@ -221,7 +228,7 @@ Amplify.configure(
221228
...amplifyConfig,
222229
API: {
223230
...amplifyConfig.API,
224-
REST: outputs.custom.API,
231+
REST: outputs.custom.API, // ← Required for custom REST APIs
225232
},
226233
},
227234
{
@@ -250,7 +257,7 @@ Amplify.configure(
250257
...amplifyConfig,
251258
API: {
252259
...amplifyConfig.API,
253-
REST: outputs.custom.API,
260+
REST: outputs.custom.API, // ← Required for custom REST APIs
254261
},
255262
},
256263
{
@@ -271,4 +278,40 @@ Amplify.configure(
271278
Make sure you call `Amplify.configure` as early as possible in your application’s life-cycle. A missing configuration or `NoCredentials` error is thrown if `Amplify.configure` has not been called before other Amplify JavaScript APIs. Review the [Library Not Configured Troubleshooting guide](/[platform]/build-a-backend/troubleshooting/library-not-configured/) for possible causes of this issue.
272279

273280
</Callout>
281+
282+
<Callout warning="true">
283+
284+
**Critical Configuration Step**: The line `REST: outputs.custom.API` is **required** to register your custom REST API. Without this, you'll encounter the error `API name is invalid` when trying to call your API.
285+
286+
</Callout>
287+
288+
## Troubleshooting
289+
290+
### "API name is invalid" Error
291+
292+
If you encounter the error `API name is invalid` when calling your REST API, ensure you have:
293+
294+
1. **Added the custom API configuration**: Include `REST: outputs.custom.API` in your `Amplify.configure()` call
295+
2. **Used the correct API name**: The API name should match the `restApiName` defined in your `backend.ts` file
296+
3. **Called `Amplify.configure()`**: Make sure configuration happens before any API calls
297+
298+
**Example of incorrect configuration** (missing custom API):
299+
```javascript
300+
// ❌ This will cause "API name is invalid" error
301+
Amplify.configure(outputs); // Missing custom REST API configuration
302+
```
303+
304+
**Correct configuration**:
305+
```javascript
306+
// ✅ This includes custom REST APIs
307+
const amplifyConfig = parseAmplifyConfig(outputs);
308+
Amplify.configure({
309+
...amplifyConfig,
310+
API: {
311+
...amplifyConfig.API,
312+
REST: outputs.custom.API, // Required for custom APIs
313+
},
314+
});
315+
```
316+
274317
</InlineFilter>

src/pages/[platform]/build-a-backend/data/connect-event-api/index.mdx

Lines changed: 2 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -346,146 +346,11 @@ let authorizer = AuthTokenAuthorizer(fetchLatestAuthToken: getUserPoolAccessToke
346346

347347
#### AWS IAM
348348

349-
If you are using Amplify Auth, you can use the following class to implement SigV4 signing logic:
350-
351-
```swift
352-
import Foundation
353-
import Amplify
354-
import AWSPluginsCore
355-
import AwsCommonRuntimeKit
356-
import AWSSDKHTTPAuth
357-
import Smithy
358-
import SmithyHTTPAPI
359-
import SmithyHTTPAuth
360-
import SmithyHTTPAuthAPI
361-
import SmithyIdentity
362-
363-
class AppSyncEventsSigner {
364-
365-
public static func createAppSyncSigner(region: String) -> ((URLRequest) async throws -> URLRequest) {
366-
return { request in
367-
try await signAppSyncRequest(request,
368-
region: region)
369-
}
370-
}
371-
372-
private static var signer = {
373-
return AWSSigV4Signer()
374-
}()
375-
376-
static func signAppSyncRequest(_ urlRequest: URLRequest,
377-
region: Swift.String,
378-
signingName: Swift.String = "appsync",
379-
date: Date = Date()) async throws -> URLRequest {
380-
CommonRuntimeKit.initialize()
381-
382-
// Convert URLRequest to SDK's HTTPRequest
383-
guard let requestBuilder = try createAppSyncSdkHttpRequestBuilder(
384-
urlRequest: urlRequest) else {
385-
return urlRequest
386-
}
387-
388-
// Retrieve the credentials from credentials provider
389-
let credentials: AWSCredentialIdentity
390-
let authSession = try await Amplify.Auth.fetchAuthSession()
391-
if let awsCredentialsProvider = authSession as? AuthAWSCredentialsProvider {
392-
let awsCredentials = try awsCredentialsProvider.getAWSCredentials().get()
393-
credentials = try awsCredentials.toAWSSDKCredentials()
394-
} else {
395-
let error = AuthError.unknown("Auth session does not include AWS credentials information")
396-
throw error
397-
}
398-
399-
// Prepare signing
400-
let flags = SigningFlags(useDoubleURIEncode: true,
401-
shouldNormalizeURIPath: true,
402-
omitSessionToken: false)
403-
let signedBodyHeader: AWSSignedBodyHeader = .none
404-
let signedBodyValue: AWSSignedBodyValue = .empty
405-
let signingConfig = AWSSigningConfig(credentials: credentials,
406-
signedBodyHeader: signedBodyHeader,
407-
signedBodyValue: signedBodyValue,
408-
flags: flags,
409-
date: date,
410-
service: signingName,
411-
region: region,
412-
signatureType: .requestHeaders,
413-
signingAlgorithm: .sigv4)
414-
415-
// Sign request
416-
guard let httpRequest = await signer.sigV4SignedRequest(
417-
requestBuilder: requestBuilder,
418-
signingConfig: signingConfig
419-
) else {
420-
return urlRequest
421-
}
422-
423-
// Update original request with new headers
424-
return setHeaders(from: httpRequest, to: urlRequest)
425-
}
426-
427-
static func setHeaders(from sdkRequest: SmithyHTTPAPI.HTTPRequest, to urlRequest: URLRequest) -> URLRequest {
428-
var urlRequest = urlRequest
429-
for header in sdkRequest.headers.headers {
430-
urlRequest.setValue(header.value.joined(separator: ","), forHTTPHeaderField: header.name)
431-
}
432-
return urlRequest
433-
}
434-
435-
static func createAppSyncSdkHttpRequestBuilder(urlRequest: URLRequest) throws -> HTTPRequestBuilder? {
436-
437-
guard let url = urlRequest.url,
438-
let host = url.host else {
439-
return nil
440-
}
441-
442-
let headers = urlRequest.allHTTPHeaderFields ?? [:]
443-
let httpMethod = (urlRequest.httpMethod?.uppercased())
444-
.flatMap(HTTPMethodType.init(rawValue:)) ?? .get
445-
446-
let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?
447-
.map { URIQueryItem(name: $0.name, value: $0.value)} ?? []
448-
449-
let requestBuilder = HTTPRequestBuilder()
450-
.withHost(host)
451-
.withPath(url.path)
452-
.withQueryItems(queryItems)
453-
.withMethod(httpMethod)
454-
.withPort(443)
455-
.withProtocol(.https)
456-
.withHeaders(.init(headers))
457-
.withBody(.data(urlRequest.httpBody))
458-
459-
return requestBuilder
460-
}
461-
}
462-
463-
extension AWSPluginsCore.AWSCredentials {
464-
465-
func toAWSSDKCredentials() throws -> AWSCredentialIdentity {
466-
if let tempCredentials = self as? AWSTemporaryCredentials {
467-
return AWSCredentialIdentity(
468-
accessKey: tempCredentials.accessKeyId,
469-
secret: tempCredentials.secretAccessKey,
470-
expiration: tempCredentials.expiration,
471-
sessionToken: tempCredentials.sessionToken
472-
)
473-
} else {
474-
return AWSCredentialIdentity(
475-
accessKey: accessKeyId,
476-
secret: secretAccessKey,
477-
expiration: nil
478-
)
479-
}
480-
}
481-
}
482-
```
483-
484-
Then, create an `IAMAuthorizer` with this helper class.
349+
If you are using Amplify Auth, you can initialize `IAMAuthorizer` with a helper method from `AWSCognitoAuthPlugin` like below:
485350

486351
```swift
487352
let authorizer = IAMAuthorizer(
488-
signRequest: AppSyncEventsSigner.createAppSyncSigner(region: "region")
353+
signRequest: AWSCognitoAuthPlugin.createAppSyncSigner(region: "region")
489354
)
490355
```
491356

src/pages/[platform]/build-a-backend/troubleshooting/cannot-find-module-amplify-env/index.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
22

33
export const meta = {
44
title: 'Troubleshoot "Cannot find module $amplify/env/<function-name>"',
5-
description: 'Addressing "Cannot find module $amplify/env/<function-name>" error message',
5+
description:
6+
'Addressing "Cannot find module $amplify/env/<function-name>" error message',
67
platforms: [
78
'angular',
89
'javascript',
10+
'flutter',
911
'nextjs',
1012
'react',
1113
'react-native',
@@ -25,7 +27,7 @@ export function getStaticProps(context) {
2527
};
2628
}
2729

28-
<InlineFilter filters={["javascript", "react-native", "angular", "nextjs", "react"]}>
30+
<InlineFilter filters={["javascript", "react-native", "angular", "flutter", "nextjs", "react"]}>
2931

3032
When deploying a Amplify Gen 2 app, you may encounter the error message `Cannot find module $amplify/env/<function-name>` in your frontend build on Amplify Console. This error occurs when your framework `tsconfig.json` configuration picks up the `amplify` directory and tries to resolve it as a module. This module is a placeholder for environment variables that are injected at build time by Amplify. To resolve this error, you need to exclude the `amplify` directory.
3133

@@ -54,7 +56,6 @@ Alternatively, if you work within a monorepo you can move your backend to its ow
5456

5557
</InlineFilter>
5658

57-
5859
<InlineFilter filters={["vue"]}>
5960

6061
When deploying a Amplify Gen 2 app, you may encounter the error message `Cannot find module $amplify/env/<function-name>` in your frontend build on Amplify Console. This error occurs when your framework `tsconfig.json` configuration picks up the `amplify` directory and tries to resolve it as a module. This module is a placeholder for environment variables that are injected at build time by Amplify. To resolve this error, you will need to include the `resource.ts` files in your `tsconfig.app.json` file.

0 commit comments

Comments
 (0)