amplify-cli icon indicating copy to clipboard operation
amplify-cli copied to clipboard

Error with _apiConfig in flutter application

Open adamtester opened this issue 1 year ago • 6 comments

Resolved, see comment below!

Description

Hello, I'm having a production issue with my app, when users login they enouncer an error, in the logs I see this:

Error encountered: LateInitializationError: Field '_apiConfig@3538173986' has not been initialized.

(referenced here: https://github.com/aws-amplify/amplify-flutter/blob/main/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart#L34)

If they force close the app and re-open, every works perfectly. Heres the part I can't work out, I checked out a commit from 40 days ago, and still I get the error, I am wondering if this is something on the backend instead (I can't revert all of these to test that theory without breaking logged in users though)

In the schema below I have a few models set to {allow: public, operations: [read]}, which I rolled back, but get the same issue.

I tested upgrading all amplify libraries to be the latest versions, and can reproduce it on iOS and Android (real and simulators)

Has anyone else encountered this issue?

Here is how I configure amplify:

class _AppState extends State<App> {
  @override
  void initState() {
    super.initState();
    _configureAmplify();
  }

  Future<void> _configureAmplify() async {
    if (Amplify.isConfigured) {
      safePrint('Amplify is already configured');
      return;
    }

    try {
      AmplifyAuthCognito authPlugin = AmplifyAuthCognito();
      AmplifyAPI apiPlugin = AmplifyAPI(modelProvider: ModelProvider.instance);
      AmplifyStorageS3 storagePlugin = AmplifyStorageS3();
      AmplifyPushNotificationsPinpoint pushPlugin =
          AmplifyPushNotificationsPinpoint();

      await Amplify.addPlugins([
        authPlugin,
        apiPlugin,
        storagePlugin,
        pushPlugin,
      ]);
      await Amplify.configure(amplifyconfig);
    } on Exception catch (e) {
      safePrint('Error configuring Amplify: $e');
    }
  }
...

Here is some sample debug code before the first error:

    _cognitoUser ??= await getCurrentCognitoUser();

    final request = ModelQueries.get(
      User.classType,
      User(id: _cognitoUser!.userId).modelIdentifier,
    );

    safePrint(_cognitoUser);
    safePrint(request.toJson());

    var creds = await Amplify.Auth.fetchAuthSession();
    safePrint(creds);

    final response = await Amplify.API.query(request: request).response; // exception happens here

And the output of that code:

flutter: CognitoAuthUser {
  "userId": "967d99a1-0000-4313-98fe-4328fb7eae18",
  "username": "google_11180577882066000000",
  "signInDetails": {
    "signInType": "hostedUi",
    "provider": {
      "name": "google",
      "identityPoolProvider": null
    }
  }
}
flutter: {id: a06d86db-0000-4b73-8f0b-dde11ff5ce38, document: query getUser($id: ID!) { getUser(id: $id) { id createdAt deletedAt username image notificationOnComment notificationOnLike notificationOnFollow emailSubscribed updatedAt owner } }, variables: {id: 967d99a1-928d-4313-98fe-4328fb7eae18}, headers: null, cancelToken: a06d86db-0000-4b73-8f0b-dde11ff5ce38, decodePath: getUser}
flutter: {
  "isSignedIn": true,
  "userSub": "AWSSuccessResult<String, AuthException> {\n  \"value\": \"967d99a1-0000-4313-98fe-4328fb7eae18\"\n}",
  "userPoolTokens": "AWSSuccessResult<CognitoUserPoolTokens, AuthException> {\n  \"value\": {\n    \"signInMethod\": \"hostedUi\",\n    \"accessToken\": \"eyJraWQiO9.....<…>
flutter: Error encountered: LateInitializationError: Field '_apiConfig@3653173986' has not been initialized.

Categories

  • [ ] Analytics
  • [ ] API (REST)
  • [X] API (GraphQL)
  • [X] Auth
  • [X] Authenticator
  • [ ] DataStore
  • [ ] Notifications (Push)
  • [ ] Storage

Steps to Reproduce

Login using Authenticator UI, then perform a API call

Screenshots

No response

Platforms

  • [X] iOS
  • [X] Android
  • [ ] Web
  • [ ] macOS
  • [ ] Windows
  • [ ] Linux

Flutter Version

3.16.8

Amplify Flutter Version

1.6.1

Deployment Method

Amplify CLI

Schema

type Comment @model @auth(
  rules: [
    {allow: owner},
    {allow: private, operations: [read]}
  ]
) {
  id: ID!
  content: String
  createdAt: AWSDateTime
  userID: ID! @index(name: "byUser")
  user: User @belongsTo(fields: ["userID"])
  projectUpdateID: ID! @index(name: "byProjectUpdate", sortKeyFields: ["createdAt"])
  projectUpdate: ProjectUpdate @belongsTo(fields: ["projectUpdateID"])
}

type Image @model @auth(
  rules: [
    {allow: owner},
    {allow: private, operations: [read]},
    {allow: public, operations: [read]}
  ]
) {
  id: ID!
  url: String!
  width: Int
  height: Int
  processed: Boolean
  projectupdateID: ID @index(name: "byProjectUpdate")
  project: Project @belongsTo
}

type Project @model @auth(
  rules: [
    {allow: owner},
    {allow: private, operations: [read]},
    {allow: public, operations: [read]}
  ]
) {
  id: ID!
  title: String!
  description: String
  views: Int
  type: String! @index(name: "projectsByDate", queryField: "projectsByDate", sortKeyFields: ["createdAt"])
  createdAt: AWSDateTime
  deletedAt: AWSDateTime
  user: User @belongsTo(fields: ["userID"])
  projectUpdates: [ProjectUpdate] @hasMany(indexName: "byProject", fields: ["id"])
  tags: [Tag] @manyToMany(relationName: "projectTags")
  userID: ID! @index(name: "byUser")
  image: Image @hasOne
}

type ProjectUpdate @model @auth(
  rules: [
    {allow: owner},
    {allow: private, operations: [read]},
    {allow: public, operations: [read]}
  ]
) {
  id: ID!
  title: String
  content: String
  type: String! @index(name: "projectUpdatesByDate", queryField: "projectUpdatesByDate", sortKeyFields: ["createdAt"])
  project: Project @belongsTo(fields: ["projectID"])
  projectID: ID! @index(name: "byProject", sortKeyFields: ["createdAt"])
  images: [Image] @hasMany(indexName: "byProjectUpdate", fields: ["id"])
  likeCount: Int @default(value: "0")
  createdAt: AWSDateTime
  comments: [Comment] @hasMany(indexName: "byProjectUpdate", fields: ["id"])
  likes: [Like] @hasMany(indexName: "byProjectUpdate", fields: ["id"]) 
}

type User @model @auth(
  rules: [
    {allow: owner},
    {allow: private, operations: [read]},
    {allow: public, operations: [read]}
  ]
) {
  id: ID!
  createdAt: AWSDateTime

  # Unused but breaks old apps if removed
  deletedAt: AWSDateTime
  projects: [Project] @hasMany(indexName: "byUser", fields: ["id"])
  username: String
  image: String
  comments: [Comment] @hasMany(indexName: "byUser", fields: ["id"])
  likes: [Like] @hasMany(indexName: "byUser", fields: ["id"])

  # Disabled: https://github.com/aws-amplify/amplify-flutter/issues/4063
  # owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])

  # When someone comments on your project update
  notificationOnComment: Boolean @default(value: "true") @auth(rules: [{allow: owner}])

  # When someone likes your project update
  notificationOnLike: Boolean @default(value: "true") @auth(rules: [{allow: owner}])

  # When someone follows you or a project
  notificationOnFollow: Boolean @default(value: "true") @auth(rules: [{allow: owner}])

  # Email notifications
  emailSubscribed: Boolean @default(value: "true") @auth(rules: [{allow: owner}])
}

type Like @model @auth(
  rules: [{allow: owner}]
) {
  id: ID!
  userID: ID! @index(name: "byUser")
  user: User @belongsTo(fields: ["userID"])
  projectUpdateID: ID! @index(name: "byProjectUpdate")
  projectUpdate: ProjectUpdate @belongsTo(fields: ["projectUpdateID"])
  owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
}

type Tag @model @auth(
  rules: [
    {allow: private, operations: [read]},
    {allow: public, operations: [read]}
  ]
) {
  id: ID!
  title: String!
  content: String
  projects: [Project] @manyToMany(relationName: "projectTags")
}

type Report @model @auth(
  rules: [
    {allow: owner, operations: [create, update, delete]}
  ]
) {
  id: ID!
  description: String
  createdAt: AWSDateTime
}

type Notification @model @auth(
  rules: [
    {allow: owner, operations: [read]}
  ]
) {
  id: ID!
  key: String @auth(rules: [{ allow: owner, operations: [read] }])
  actionUser: User @hasOne @auth(rules: [{ allow: owner, operations: [read] }])
  project: Project @hasOne @auth(rules: [{ allow: owner, operations: [read] }])
  read: Boolean @auth(rules: [{ allow: owner, operations: [read, update] }])
  owner: String @auth(rules: [{ allow: owner, operations: [read] }]) @index(name: "byOwner", sortKeyFields: ["createdAt"])
  createdAt: AWSDateTime
}

adamtester avatar Jan 30 '24 21:01 adamtester

Hello, an update on my side, I have managed to fix it by commenting out the Push notificaiton plugin:

AmplifyPushNotificationsPinpoint pushPlugin =
          AmplifyPushNotificationsPinpoint();

This was throwing an exception during the config step:

flutter: Error encountered: SignedOutException {
  "message": "No user is currently signed in"
}
flutter: Error configuring Amplify: PushNotificationException {
  "message": "Error occurred awaiting for device token to register device with Pinpoint",
  "recoverySuggestion": "Please review the underlying exception",
  "underlyingException": "UnknownException {\n  \"message\": \"The AWS credentials could not be retrieved\",\n  \"recoverySuggestion\": \"Invoke Amplify.Auth.signIn to re-authenticate the user\",\n  \"underlyingException\": \"NotAuthorizedException {\\n  message=Unauthenticated access is not supported for this identity pool.,\\n}\"\n}"
}

And I assume that this failed to register the fact the Amplify.API package had credentials.

Checking the documentation over here states to register the plug as I have done:

  Future<void> _configureAmplify() async {
    try {
      final authPlugin = AmplifyAuthCognito();
      final pushPlugin = AmplifyPushNotificationsPinpoint();
      await Amplify.addPlugins([authPlugin, pushPlugin]);
      await Amplify.configure(amplifyconfig);
    } on Exception catch (e) {
      safePrint('An error occurred configuring Amplify: $e');
    }
  }

So it looks like I need to try and register the plugin after the user has authenticated?

adamtester avatar Jan 31 '24 16:01 adamtester

Looks like the same issue as this issue: https://github.com/aws-amplify/amplify-flutter/issues/3690

Testing the comment here: https://github.com/aws-amplify/amplify-flutter/issues/3690#issuecomment-1706916904

In the config, seems like it is enabled:

{
  "version": "1",
  "cognitoConfig": {
    "identityPoolName": "xxxf84b7594_identitypool_f84b7594",
    "allowUnauthenticatedIdentities": true,
...

However amplify update auth returns nothing to update

Checking in the console however: image

I enabled it manually and it resolves me original issue, but I'm concerned that it will be disabled in the next amplify push

adamtester avatar Jan 31 '24 16:01 adamtester

Hi @adamtester, which method did you end up going through when you manually enabled unauthenticated access? Did you change the config, change it manually in the console, or through the CLI (I'm guessing not the CLI because you said it returns nothing to update)? I'm going to transfer this issue to the amplify-cli repo to better help you in this case.

khatruong2009 avatar Feb 01 '24 19:02 khatruong2009

@adamtester was the unauthenticated access enabled by running

  1. amplify update auth
  2. select Walkthrough all the auth configurations
  3. On Allow unauthenticated logins select Yes
  4. then run amplify push

ykethan avatar Feb 02 '24 14:02 ykethan

Hey @khatruong2009 and @ykethan to enable it, I manually did it in the UI.

When running the steps it just said Nothing to update so I assume the Cloudformation had drifted (not sure how it is checking that, or if it just checks the config jsons?)

adamtester avatar Feb 03 '24 12:02 adamtester

@adamtester interesting, could you try running amplify push --force? the walkthrough is expected to update the cli-inputs.json file present at the amplify/auth/<resource-name>

ykethan avatar Feb 06 '24 18:02 ykethan

Closing the issue due to inactivity. Do reach out to us if you require any assistance.

ykethan avatar May 03 '24 15:05 ykethan

This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.

github-actions[bot] avatar May 03 '24 15:05 github-actions[bot]