Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataStore - Sync processor retry error: {"data": {}, "errors": [[GraphQLError: Request failed with status code 401]]} #12951

Open
4 tasks done
elkee2003 opened this issue Feb 2, 2024 · 8 comments
Labels
DataStore Related to DataStore category pending-maintainer-response Issue is pending a response from the Amplify team. question General question

Comments

@elkee2003
Copy link

elkee2003 commented Feb 2, 2024

Before opening, please confirm:

App Id

arn:aws:amplify:us-east-1:115372163617:apps/dnxdny8iom5jq

Region

us-east-1

Environment name

VS code

Figma File Version (if applicable)

No response

Amplify CLI Version

12.8.2

If applicable, what version of Node.js are you using?

v20.11.0

What operating system are you using?

Windows

Browser type?

Google Chrome

Describe the bug

I keep getting this bug: [ERROR] 05:24.121 DataStore - Sync processor retry error: {"data": {}, "errors": [[GraphQLError: Request failed with status code 401]]} I don't know why.
Theses are where Datastore is used:

import '@azure/core-asynciterator-polyfill'
import { View, Text, TextInput, Button, Pressable, Alert } from 'react-native'
import React, {useEffect, useState, } from 'react'
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import { Auth, DataStore } from 'aws-amplify'
import { User } from '../../models'
import styles from './styles'
import { useAuthContext } from '../../contexts/AuthContext'
import { useNavigation } from '@react-navigation/native'


const ProfileScreen = () => {

  const {sub, dbUser, setDbUser} = useAuthContext()
  
    const [name, setName] = useState(dbUser?.name || "")
    const [address, setAddress] = useState(dbUser?.address || "")
    const [phoneNumber, setPhoneNumber]= useState(dbUser?.phoneNumber || "")
    const [lat, setLat] = useState(dbUser?.lat.toString() || "0")
    const [lng, setLng] = useState (dbUser?.lng.toString() || "0") 
    
    const [isFocused, setIsFocused] = useState(false);
   
    const navigation = useNavigation()

    // Start of Function to Create and Update User
    const createUser = async ()=>{
      try{
        const user = await DataStore.save(new User({
         name, 
         address,
         phoneNumber,
         lat:parseFloat(lat), 
         lng:parseFloat(lng), 
         sub
       })
       );
       console.log("I am User:",user)
       setDbUser(user)
     }catch(e){
       Alert.alert("Error", e.message)
     }
    }

    const updateUser= async ()=>{
      const user = await DataStore.save(User.copyOf(dbUser, (updated)=>{
        updated.name = name;
        updated.address = address;
        updated.phoneNumber = phoneNumber
        updated.lat = parseFloat(lat);
        updated.lng = parseFloat(lng);
      }))
      setDbUser(user)
    }
    // End Of Function to Create and Update User

    // Function to Save Data
    const onSave= async()=>{
      if(dbUser){
        await updateUser()
        navigation.goBack()
      }else{
        await createUser()
        navigation.navigate('HomeScreen')
      }
      // navigation.goBack()
    }

    // function to handle focus
    const handleFocusChange = (focused) => {
      setIsFocused(focused);
    };

    // Start Of GooglePlacesAutoComplete
    const handlePlaceSelect = (data, details = null) => {
      // Extract the address from the selected place
      const selectedAddress = details?.formatted_address || data.description;

      console.log( "Show the Lat, and Lng data and details:",data,details)
  
      // Update the address state
      setAddress(selectedAddress);
  
    };
    // End Of GooglePlacesAutoComplete

    return (
    <View style={styles.container}>

      <Text style={styles.title}>Profile</Text>

      <TextInput 
      value={name}
      onChangeText={setName}
      placeholder='Name'
      style={styles.input}
      />

      <TextInput 
      value={address}
      placeholder='Address'
      style={{...styles.input, color: '#04df04'}}
      />

      <View style={isFocused ? styles.gContainerFocused : styles.gContainer}>
        <GooglePlacesAutocomplete
        placeholder='Select Address From Here'
        onPress={handlePlaceSelect}
        textInputProps={{
          onFocus:() => handleFocusChange(true),
          onBlur:() => handleFocusChange(false)
        }} 
        styles={{
          textInput:styles.gTextInput,
          textInputContainer:styles.gTextInputContainer,
          listView:styles.glistView,
          poweredContainer:styles.gPoweredContainer
        }}
        query={{
          key: 'AIzaSyAY',
          language: 'en',
        }}
        />
      </View>

    {/* TextInputs that will be below GooglePlacesAutocomplete */}
    
      <TextInput
      value={phoneNumber}
      onChangeText={setPhoneNumber}
      placeholder='Phone Number'
      style={styles.input}
      />

      <TextInput 
      value={lat}
      onChangeText={setLat}
      placeholder='Latitude'
      keyboardType='numeric'
      style={styles.input}
      />

      <TextInput 
      value={lng}
      onChangeText={setLng}
      placeholder='Longitude'
      keyboardType='numeric'
      style={styles.input}
      />

      <View style={styles.scrnBtn}>
        {/* Save */}
        <Pressable onPress={onSave
        } style={styles.saveBackground}>
          <Text style={styles.save}>
            Save
          </Text>
        </Pressable>
        
        {/* SignOut */}
        <Pressable onPress={()=>{Auth.signOut
        ()}}>
          <Text style={styles.signOut}>
            Sign out
          </Text>
        </Pressable>
      </View>
      
    </View>
  )
}

export default ProfileScreen
import { createContext, useState,useEffect, useContext } from "react";
import {Auth, DataStore, Amplify, Predicates} from 'aws-amplify';
import { User } from "../models";
  

const AuthContext = createContext({})

const AuthContextProvider = ({children})=>{

    const [authUser, setAuthUser] = useState(null)
    const [dbUser, setDbUser] = useState(null)
    const sub = authUser?.attributes?.sub;

    useEffect(()=>{
        Auth.currentAuthenticatedUser({bypassCache: true}).then(setAuthUser)
    },[]);

    useEffect(()=>{
        DataStore.query(User, (user)=>user.sub.eq(sub)).then((users)=>setDbUser(users[0]))
        console.log(dbUser)
        
    }, [sub])

    return(
        <AuthContext.Provider value={{authUser, dbUser, sub, setDbUser, }}>
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContextProvider;

export const useAuthContext = ()=> useContext(AuthContext)

Expected behavior

It used to work, all of a sudden it stopped

Reproduction steps

  1. run the code I pasted
  2. it will then give you this error [ERROR] 05:24.121 DataStore - Sync processor retry error: {"data": {}, "errors": [[GraphQLError: Request failed with status code 401]]}

Project Identifier

No response

Additional information

No response

@elkee2003 elkee2003 added the pending-triage Issue is pending triage label Feb 2, 2024
@elkee2003
Copy link
Author

Screenshot (82)
Screenshot (83)
These are screenshots of the error

@ykethan
Copy link
Member

ykethan commented Feb 2, 2024

Hey,👋 thanks for raising this! I'm going to transfer this over to our Amplify JS repository for better assistance 🙂

@ykethan ykethan transferred this issue from aws-amplify/amplify-studio Feb 2, 2024
@cwomack cwomack self-assigned this Feb 2, 2024
@cwomack cwomack added the DataStore Related to DataStore category label Feb 2, 2024
@chrisbonifacio
Copy link
Member

Hi @elkee2003 👋 it looks like your error logs mention UnuathorizedExceptions for create and update User operations, and the sync is failing with auth mode API_KEY. You might have to enable MULTI_AUTH on your DataStore configuration so that it uses your other auth modes like COGNITO_USER_POOLS.

Please refer to the docs to configure MULTI_AUTH:
https://docs.amplify.aws/javascript/build-a-backend/more-features/datastore/authz-rules-setup/#configure-multiple-authorization-types

@cwomack cwomack added question General question and removed pending-triage Issue is pending triage labels Feb 14, 2024
@cwomack
Copy link
Member

cwomack commented Feb 14, 2024

@elkee2003, let us know if you had a chance to review @chrisbonifacio's comment above and if it unblocked you.

@elkee2003
Copy link
Author

@elkee2003, let us know if you had a chance to review @chrisbonifacio's comment above and if it unblocked you.

No I haven't had the chance to try it out, once I try it out I'll let him know

@elkee2003
Copy link
Author

It does not work. Just to be clear after I run this:
`import { DataStore, AuthModeStrategyType } from 'aws-amplify/datastore';

DataStore.configure({
authModeStrategyType: AuthModeStrategyType.MULTI_AUTH
});`
is it meant to solve the problem?

@chrisbonifacio
Copy link
Member

Hi @elkee2003 I thought it might resolve the problem because the error says that the user is not authorized perform the query using API_KEY as an auth mode. Can you share your schema so we can confirm this is expected behavior?

By default DataStore will attempt to authorize qraphql calls to AppSync only using the default auth mode mentioned in the amplifyconfiguration.json file. MULTI_AUTH allows DataStore to use additional auth modes, of which it will re-attempt calls with. If you look at the hierarchy of auith modes it retries with, API_KEY is the last one because it goes from least to most permissive auth rules.

If you are still getting unauthorized errors with multi auth enabled, then we need to take a look at the schema to figure out how the auth rules are configured on the model and what auth mode DataStore should be able to authorize a user with.

@elkee2003
Copy link
Author

Hi @elkee2003 I thought it might resolve the problem because the error says that the user is not authorized perform the query using API_KEY as an auth mode. Can you share your schema so we can confirm this is expected behavior?

By default DataStore will attempt to authorize qraphql calls to AppSync only using the default auth mode mentioned in the amplifyconfiguration.json file. MULTI_AUTH allows DataStore to use additional auth modes, of which it will re-attempt calls with. If you look at the hierarchy of auith modes it retries with, API_KEY is the last one because it goes from least to most permissive auth rules.

If you are still getting unauthorized errors with multi auth enabled, then we need to take a look at the schema to figure out how the auth rules are configured on the model and what auth mode DataStore should be able to authorize a user with.

enum OrderStatus {
READY_FOR_PICKUP
ACCEPTED
PICKEDUP
DELIVERED
}

type Order @model @auth(rules: [{allow: public}]) {
id: ID!
recipientName: String!
recipientNumber: String!
orderDetails: String
total: Float
status: OrderStatus!
userID: ID! @index(name: "byUser")
originPlace: String
destinationPlace: String
}

type User @model @auth(rules: [{allow: public}]) {
id: ID!
sub: String!
name: String!
phoneNumber: String!
lng: Float!
Orders: [Order] @hasmany(indexName: "byUser", fields: ["id"])
lat: Float!
address: String!
}

@nadetastic nadetastic added the investigating This issue is being investigated label Mar 7, 2024
@chrisbonifacio chrisbonifacio removed their assignment May 20, 2024
@cwomack cwomack added pending-maintainer-response Issue is pending a response from the Amplify team. and removed investigating This issue is being investigated labels Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DataStore Related to DataStore category pending-maintainer-response Issue is pending a response from the Amplify team. question General question
Projects
None yet
Development

No branches or pull requests

5 participants