Describe the bug
I have followed https://aws-amplify.github.io/docs/js/datastore to create demo angular application for offline syncup with API and datastore. but it is showing below error.
ConsoleLogger.js:94 [WARN] 26:09.704 DataStore - Sync error subscription failed Connection failed:
{"errors":[
{"message":"Validation error of type FieldUndefined: Field '_version' in type 'Post' is undefined @ 'onCreatePost/_version'"},
{"message":"Validation error of type FieldUndefined: Field '_lastChangedAt' in type 'Post' is undefined @ 'onCreatePost/_lastChangedAt'"},
{"message":"Validation error of type FieldUndefined: Field '_deleted' in type 'Post' is undefined @ 'onCreatePost/_deleted'"}]}
message: "Validation error of type FieldUndefined: Field 'syncPosts' in type 'Query' is undefined @ 'syncPosts'"
To Reproduce
Steps to reproduce the behavior:
ng new testApp
cd testApp
npm install -g @aws-amplify/cli
amplify configure
npm install --save aws-amplify
npm install --save aws-amplify-angular
amplify init
[Note the selected steps:
? Choose the type of app that you're building: javascript
? Please tell us about your project? What javascript framework are you using: angular]
amplify add api
[Note the steps Selected:
? Choose an authorization type for the API Amazon: API Key
? Do you have an annotated GraphQL schema? No
? Do you want a guided schema creation? Yes
? What best describes your project: Single object with fields (e.g., “Todo” with ID, name, description)
? Do you want to edit the schema now? Yes
]
Schema added in amplify/backend/api/amplifyapi/schema.graphql is as below:
type Todo @model {
id: ID!
name: String!
description: String
}
enum PostStatus {
ACTIVE
INACTIVE
}
type Post @model {
id: ID!
title: String!
rating: Int!
status: PostStatus!
}
amplify codegen models
Now add below lines in main.ts
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);
Add below code in app.component.ts
import { DataStore, Predicates } from '@aws-amplify/datastore';
import { Post, PostStatus } from '../../models';
import {from, Observable} from 'rxjs';
on ngOnInit hook add below code:
await DataStore.save(
new Post({
title:
Created! ${Date.now()},
rating: 1,
status: PostStatus.ACTIVE
})
);
After that it shows added record using below code:
this.postlist = await DataStore.query(Post as any);
console.log(this.postlist);
Everything works fine up to this as this is in local data store only.
Now i want to sync this with aws cloud dynamodb. so i run below command
amplify push
and add below code to observe and sync data dynamically to ngOnInit hook in my app component:
DataStore.observe(Post as any).subscribe(msg => {
this.postlist = await DataStore.query(Post as any);
console.log(this.postlist);
});
After adding above code, expected behavior is it should syncup local data to dynamodb cloud but it is not.
At this stage it is not syncing with cloud and showing below error:
ConsoleLogger.js:94 [WARN] 26:09.704 DataStore - Sync error subscription failed Connection failed:
{"errors":[
{"message":"Validation error of type FieldUndefined: Field '_version' in type 'Post' is undefined @ 'onCreatePost/_version'"},
{"message":"Validation error of type FieldUndefined: Field '_lastChangedAt' in type 'Post' is undefined @ 'onCreatePost/_lastChangedAt'"},
{"message":"Validation error of type FieldUndefined: Field '_deleted' in type 'Post' is undefined @ 'onCreatePost/_deleted'"}]}
message: "Validation error of type FieldUndefined: Field 'syncPosts' in type 'Query' is undefined @ 'syncPosts'"
Note that everything working fine in local but issue is with syncup with cloud.
Note: I did not run npx amplify-app@latest
command
My package.json is:
{
"name": "testApp",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~8.2.4",
"@angular/common": "~8.2.4",
"@angular/compiler": "~8.2.4",
"@angular/core": "~8.2.4",
"@angular/forms": "~8.2.4",
"@angular/platform-browser": "~8.2.4",
"@angular/platform-browser-dynamic": "~8.2.4",
"@angular/router": "~8.2.4",
"@aws-amplify/core": "^2.2.2",
"@aws-amplify/datastore": "^1.0.4",
"@ng-bootstrap/ng-bootstrap": "^5.2.1",
"aws-amplify": "^2.2.2",
"aws-amplify-angular": "^4.1.3",
"bootstrap": "^4.4.1",
"buffer": "^5.4.3",
"rxjs": "~6.4.0",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.803.2",
"@angular/cli": "~8.3.2",
"@angular/compiler-cli": "~8.2.4",
"@angular/language-service": "~8.2.4",
"@types/node": "~8.9.4",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.5.3"
}
}
Expected behavior
It should syncup local data to cloud dynamo db. but is is not storing data in cloud dynamodb
@miteshgodhani which amplify cli version do you have?
(run amplify -v
on your terminal)
@elorzafe amplify version: 4.13.1
@elorzafe I am stuck with this error. can some please help me here? I have tried with multiple fresh new project to fix this but getting same error every time.
I'm having a similar issue:
WARN] 14:51.105 DataStore - Sync error subscription failed Connection failed: {"errors":[{"message":"Validation error of type FieldUndefined: Field 'startDate' in type 'Timeline' is undefined @ 'onCreateTimeline/startDate'"},{"message":"Validation error of type FieldUndefined: Field 'endDate' in type 'Timeline' is undefined @ 'onCreateTimeline/endDate'"}]}
Besides using Vue instead of Angular, it's pretty much the same configuration. Same Amplify-CLI version, 4.13.1
I'm getting the same error, react + typescript here.
Sync error subscription failed Connection failed: {"errors":[{"message":"Validation error of type FieldUndefined: Field '_version' in type 'Ting' is undefined @ 'onDeleteTing/_version'"},{"message":"Validation error of type FieldUndefined: Field '_lastChangedAt' in type 'Ting' is undefined @ 'onDeleteTing/_lastChangedAt'"},{"message":"Validation error of type FieldUndefined: Field '_deleted' in type 'Ting' is undefined @ 'onDeleteTing/_deleted'"}]}
amplify-cli 4.13.0
@aws-amplify/core 2.2.4
@aws-amplify/datastore 1.0.6
@aws-amplify/pubsub 2.1.5
I was asked to add my sample code for debugging:
type Ting
@model
@auth(
rules: [
{ allow: owner }
{
allow: groups
groups: ["admins"]
queries: [get, list]
mutations: [create, update, delete]
}
]
) {
id: ID!
references: [TingRef] @connection(keyName: "byChild", fields: ["id"])
referencedBy: [TingRef] @connection(keyName: "byParent", fields: ["id"])
content: String!
access: [UserTing] @connection(keyName: "byUser", fields: ["id"])
}
type TingRef
@model(queries: null)
@auth(
rules: [
{ allow: owner }
{
allow: groups
groups: ["admins"]
queries: [get, list]
mutations: [create, update, delete]
}
]
)
@key(name: "byChild", fields: ["childID", "parentID"])
@key(name: "byParent", fields: ["parentID", "childID"]) {
id: ID!
parentID: ID!
childID: ID!
parent: Ting! @connection(fields: ["parentID"])
child: Ting! @connection(fields: ["childID"])
}
type UserTing
@model(queries: null)
@auth(
rules: [
{ allow: owner }
{
allow: groups
groups: ["admins"]
queries: [get, list]
mutations: [create, update, delete]
}
]
)
@key(name: "byTing", fields: ["tingID", "userID"])
@key(name: "byUser", fields: ["userID", "tingID"]) {
id: ID!
userID: ID!
tingID: ID!
user: Ting! @connection(fields: ["userID"])
ting: Ting! @connection(fields: ["tingID"])
}
type User
@model
@auth(
rules: [
{ allow: owner }
{
allow: groups
groups: ["admins"]
queries: [get, list]
mutations: [create, update, delete]
}
]
) {
id: ID!
email: String
emails: [String]
name: String
tings: [UserTing] @connection(keyName: "byTing", fields: ["id"])
}
import React, { useState, useEffect } from "react";
import { DataStore, Predicates } from "@aws-amplify/datastore";
import { Ting } from "../../models";
import { SaveTing } from "../SaveTing";
export const Feed = () => {
const [tings, setTings] = useState<Array<Ting>>([]);
async function fetchTings() {
const newTings: any = await DataStore.query(Ting);
setTings(newTings);
}
useEffect(() => {
// const subscription = DataStore.observe(Ting).subscribe(msg => {
// console.log(msg.model, msg.opType, msg.element);
// });
fetchTings();
}, []);
return (
<section>
Feed
<SaveTing />
{tings.map((t: Ting) => (
<article key={t.id}>
{t.id}: {t.content}
</article>
))}
</section>
);
};
@miteshgodhani @raelmiu
Looks like the provisioned APIs are not sync-enabled (meaning that they will not work with DataStore). I come to this conclusion because the missing fields mentioned in your logs (_version
, _deleted
and _lastChangedAt
) are part of sync-enabled apis provisioned by the amplify cli / npx scripts
Did you get a question like this when doing the amplify add api
step?
? Do you want to configure advanced settings for the GraphQL
This flow in the CLI is the one that creates a sync-enabled (datastore) API.
Another option you can try is with the npx/npm scripts flow:
npx amplify-app@latest
and npm run amplify-modelgen
/npm run amplify-push
Thank you for reporting this, there is clearly room for improvement in the flows and docs. We'll be exploring ways to make this information better/clearer and the flows more intuitive.
@manueliglesias I don't think this is a documentation issue, that's the flow I went through. I have also run amplify-modelgen.
As you can see from the included screenshot the meta fields ("_deleted" etc) are there locally, just undefined. But I have no idea why it's undefined. Since this is handled by DataStore.
This is my browser DB of the same model:
@manueliglesias Yes, you are right. it worked with ? Do you want to configure advanced settings for the GraphQL
.
thanks for help and update.
As you mentioned above, please update document as soon as possible.
@miteshgodhani So you just re-rean the API configuration and it started working?
@raelmiu yes, and while re-run, select option ? Do you want to configure advanced settings for the GraphQL
for merge conflict configuration.
It worked for me as well, to go through amplify update api
and do no changes. The tables are back to updating.
advance configuration for graphql resolved this issue. need to update documentation.
Just tried this:
amplify update api
configure advanced settings
merge conflict settings
npm run amplify codegen
.No change. Still all undefined. Any other things you tried? Updated versions? (Ping @manueliglesias since this is closed now.)
Turns out I was wrong. It DOES work now. I just also had to delete all existing objects both locally and in the dynamoDb.
I've just run into this problem again. With many-to-many relationships the middle model cannot be saved. Debugging as we speak. But I'm surprised these similar issues keep appearing.
@raelmiu Can you share your schema?
Also, just to verify, are you doing amplify push after doing local changes to the schema/models ?
@manueliglesias it's the same one as above. But I'm not sure this is the same error but here's what I've discovered while debugging:
When I try to save a new Ting and a new TingRef (relationship between two Tings)
const savedReferences: any = await DataStore.save(
new TingRef({
child: childTing,
parent: parentTing
})
);
I get the following debug log:
[DEBUG] 23:20.734 Util - attempt #1 with this vars: ["TingRef","Create","{\"id\":\"149da9dc-ab3b-4719-a582-93c9f3c809d7\",\"parentID\":\"b6515274-7a5b-4986-9933-a03637b7e920\",\"childID\":\"056a2ff9-f0cc-496d-b052-2769a440ce45\"}","{}",null,null,{"data":"{\"id\":\"149da9dc-ab3b-4719-a582-93c9f3c809d7\",\"parentID\":\"b6515274-7a5b-4986-9933-a03637b7e920\",\"childID\":\"056a2ff9-f0cc-496d-b052-2769a440ce45\"}","modelId":"149da9dc-ab3b-4719-a582-93c9f3c809d7","model":"TingRef","operation":"Create","condition":"{}","id":"11ea-554c-955fa410-89bd-950acc75f5eb"}]
and this DataStore warning:
"Variable 'input' has coerced Null value for NonNull type 'TingInput!'"
From that I believe that one of the Ting's still has undefined
parameters. And logging it, the new Ting is missing both _version
and _lastChangedAt
.
So I created temp models and use them instead:
let tempParent = {
id: newEntityTing[0].id,
content: newEntityTing[0].content,
_version: 1,
_lastChangedAt: Date.now()
};
const savedReferences: any = await DataStore.save(
new TingRef({
child: tempChild as Ting,
parent: tempParent as Ting
})
);
This however, results in the exact same error, which makes me think TingRef is still not initialised correctly by amplify?
In both these examples the models are being created and stored locally.
But there's nothing in the DynamoDb.
@manueliglesias I just added two new fields to my Ting model to try to work around this relationship issue. And now nothing is syncing, not up OR down.
(I added them in schema.graphql, ran the amplify push, the codegen)
Which is interesting.
Could it be that any changes to an API breaks the API? That doesn't sound likely, but something strange is clearly happening here.
@raelmiu did you push your updates with amplify push
and also re-run model-gen locally?
I have the same issue, i ran coden and amplify push and not refresh, i read about amplify update api, and this not fix the issue, maybe is a update error in schema in the cloud.
@CarlitosBeto can you post your schema, app code, and the workflow you followed? For instance:
@CarlitosBeto can you post your schema, app code, and the workflow you followed? For instance:
- Starting schema
- model gen
- Initial app code
- pushed
- Updated schema to look like XYZ
- model gen
- pushed
- Updated app code
Sure this is my schema:
type Employee
@model @versioned
@key(name: "ByEmail", fields: ["email"], queryField: "employeesByEmail") {
id: ID!
createdAt: AWSDateTime
UpdatedAt: AWSDateTime
firstName: String!
lastName: String
fullName: String
dateOfBirth: AWSDateTime
identification: String
email: AWSEmail!
tramite: [Tramite]
@connection(name: "EmployeeTramite", keyField: "inspectorId")
inspectorId: ID
team: Team! @connection(name: "TeamEmployee", keyField: "teamId") #! cambio para compilar mobile
teamId: ID #ID!
rol: Rol @connection(name: "RolEmployee", keyField: "rolId")
rolId: ID
teamMan: Team! @connection(name: "TeamManager", keyField: "teamIdMan") #! cambio para compilar mobile
teamIdMan: ID #ID!
company: Company
@connection(name: "CompanyEmployee", keyField: "companyIdEmp")
companyIdEmp: ID
login: [Login] @connection(name: "EmpleadoLogin")
image: String
cambioEstado: CambioEstado @connection(name: "CambioEstadoEmpleado")
}
type Team @model @versioned {
id: ID!
name: String!
employees: [Employee] @connection(name: "TeamEmployee", keyField: "teamId")
teamId: ID
manager: Employee @connection(name: "TeamManager", keyField: "teamIdMan")
teamIdMan: ID!
tramite: [Tramite] @connection(name: "TeamTramite", keyField: "teamId")
}
type Channel @model @versioned {
id: ID!
firstName: String!
lastName: String
dateOfBirth: AWSDateTime
email: AWSEmail
}
type Company @model @versioned {
id: ID!
name: String!
address: String
logo: String
employees: [Employee]
@connection(name: "CompanyEmployee", keyField: "companyIdEmp")
companyIdEmp: ID
tramite: [Tramite] @connection(name: "CompanyTramite", keyField: "companyId")
companyId: ID
#grupo: Grupo @connection(name: "CompanyGrupo")
}
type Rol @model @versioned {
id: ID!
name: String!
empleado: [Employee] @connection(name: "RolEmployee", keyField: "rolId")
products: [Product] @connection(name: "RolProduct", keyField: "rolId")
}
type Product
@model @versioned
@key(name: "ByRolId", fields: ["rolId"], queryField: "productByRolId") {
id: ID!
name: String!
menu: AWSJSON
rol: Rol @connection(name: "RolProduct", keyField: "rolId")
rolId: ID
}
type Tramite
@model @versioned
@key(
name: "tramiteInspector"
fields: ["inspectorId"]
queryField: "tramiteInspector"
)
@key(
name: "tramiteTipoNum"
fields: ["tipo", "numTramite"]
queryField: "tramiteTipoNum"
) {
#@searchable
id: ID!
createdAt: AWSDateTime
numTramite: String!
oficialNegocio: String
nombreApellido: String
cedula: String
direccion: String
telefonos: String
tipoNegocio: String
destinoCredito: String
afct: String
monto: String
nombreApellido_IN: String
cedula_IN: String
direccion_IN: String
telefonos_IN: String
tipoNegocio_IN: String
destinoCredito_IN: String
afct_IN: String
monto_IN: String
direccionInversion: String
ruralUrbano: String
extension: String
esPropio: Boolean
esGravamen: Boolean
propietario: String
coorUTMZ: String
coorUTML: String
coorUTME: String
coorUTMN: String
uPLat: Float
uPLon: Float
descripcion: String
inventario: String
otrosActivos: String
observaciones: String
nombreApellidosGarante: String
cedulaGarante: String
direccionGarante: String
direccionHipoteca: String
telefonoGarante: String
nombreApellidosGarante_IN: String
cedulaGarante_IN: String
direccionGarante_IN: String
direccionHipoteca_IN: String
telefonoGarante_IN: String
inspector: Employee
@connection(name: "EmployeeTramite", keyField: "inspectorId")
inspectorId: ID
estado: TramiteEstado!
canton: String
provincia: String
agencia: String
regional: RegionalTramite
tipo: TipoTramite!
company: Company @connection(name: "CompanyTramite", keyField: "companyId")
companyId: ID
team: Team @connection(name: "TeamTramite", keyField: "teamId")
teamId: ID
cambioEstado: CambioEstado
@connection(name: "CambioEstadoTramite", keyField: "tramiteId")
observacion: String
grupo: Grupo @connection(name: "GrupoTramite", keyField: "grupoId")
grupoId: ID
imagen: [String]
fechaInspeccion: AWSDateTime
tipoProyecto: String
tipoPropiedad: String
parroquia: String
referencias: String
barrio: String
linderoNorte: String
linderoSur: String
linderoEste: String
linderoOeste: String
edificaciones: String
terreno: String
localComercial: String
infraestructuras: String
riesgosPotenciales: String
inventarioComercial: String
vivienda: String
herramientas: String
terrenos: String
unidadesProductivas: String
vehiculos: String
ingresosDemostrables: String
maquinarias: String
tipoGarantia: String
actEconPer: String
edificacionesHip: String
terrenoHip: String
extHip: String
localComercialHip: String
riesgosPotHip: String
observacionesHip: String
descripcionOtros: String
provinciaUbi: String
direccionUbi: String
cantonUbi: String
parroquiaUbi: String
referenciasUbi: String
barrioUbi: String
coorUTMZUbi: String
coorUTMLUbi: String
coorUTMEUbi: String
coorUTMNUbi: String
linderoNorteUbi: String
linderoSurUbi: String
linderoEsteUbi: String
linderoOesteUbi: String
firmaCliente: String
firmaGarante: String
}
type Login @model @versioned {
id: ID!
empleado: Employee @connection(name: "EmpleadoLogin")
fecha: AWSTimestamp
coords: AWSJSON
}
enum RegionalTramite {
IBARRA
QUITO
RIOBAMBA
PORTOVIEJO
GUAYAQUIL
CUENCA
LOJA
}
enum TipoTramite {
INSPECCION
REINSPECCION
VERIFICACION
}
enum TramiteEstado {
CARGADO #SUBE INF AL SISTEMA
AGENDADO #EQUIPO O PROP
REAGENDADO #EQUIPO O PROP /PRIORIDAD UNO
INSPECCION #EN INSPECCIÓN
PROCESANDO #AUN TRABAJO
FINALIZADO #TRABAJO INSP TERMINADO
VALIDANDO #TRABAJO VALIDADOR
CERRADO #LISTO PARA CLIENTE
}
type CambioEstado @model @versioned {
id: ID!
createdAt: AWSDateTime
estadoInicial: TramiteEstado
estadoFinal: TramiteEstado
tramite: [Tramite]
@connection(name: "CambioEstadoTramite", keyField: "tramiteId")
tramiteId: ID
usuario: Employee!
@connection(name: "CambioEstadoEmpleado", keyField: "employeeId")
employeeId: ID! #compila mobile
}
type Grupo @model @versioned {
id: ID!
createdAt: AWSDateTime
#company: Company @connection(name: "CompanyGrupo")
companyId: ID
nombre: String
tramite: [Tramite] @connection(name: "GrupoTramite", keyField: "grupoId")
grupoId: ID
fechaAsignacion: AWSDateTime
}
type Embarcacion @model @versioned {
id: ID!
createdAt: AWSDateTime
nombre: String
contactoPrincipal: String
tramite: String
ci_ruc: String
estadoCallCenter: String
observacion: String
representanteLegal: String
ceduladeIdentidadRL: String
apellidosRL: String
nombresRL: String
provincia: String
canton: String
parroquia: String
telefonoConvencional: String
telefonoMovil: String
correoElectronico: String
nombreEmbarcacion: String
matricula: String
puertoRegistro: String
tipodeNave: String
material: String
esloraTotal: String
esloraConvenio: String
manga: String
puntal: String
calado: String
tonelajeBruto: String
tonelajeNeto: String
valorEmbarcacion: String
totalMotor: String
totalAccesorios: String
totalArtes: String
avaluo: String
fechaAvaluo: String
ValorEmbarcacion: String
Serviciopesca: String
FechaConstruccion: String
FechaRegistro: String
TipoCasco: String
Propulsion: String
TipoCombustible: String
Motor1: String
Tipo1: String
Marca1: String
Modelo1: String
Potencia1: String
Troquelado1: String
Motor2: String
Tipo: String
Marca: String
Modelo: String
Potencia: String
Troquelado: String
GPS: String
Brujula: String
Ecosonda: String
Radio: String
Celular: String
Otros: String
EquiposAuxilio: String
ChalecosSalvavidas: String
LucesBengala: String
Boyasflotadores: String
}
First i generate the code / api for angular and expo.io project, then i try to use datastore and update my api with the instructions founded in amplify use datastore.
I change my code in angular app for new field (version / versionexpected) and run the app web but in my code in expo i can't run datastore.query
I forgot: In appsync i could ran query asyncTramite
Thanks for you reply
@CarlitosBeto I see the issue. The @versioned
directive cannot be used with DataStore. That is an older directive that predates this new functionality when all the optimistic locking was done in a resolver. With the new release this is all done in AppSync for you. Can you remove those directives and try from scratch in a new app?
@raelmiu did you push your updates with
amplify push
and also re-run model-gen locally?
Yes I did. The models/schema.js look fine.
Updated amplify-CLI from 4.13.3 to 4.13.4 and tried again:
amplify push
npm run amplify-modelgen
Nothing happened, remembered an earlier problem where I had to remove the local DB. So I cleared the entire local cache, logged in again and then:
Things are being synced down. But DataStore cannot populate:
Uncaught (in promise) Error: Field refs should be of type string[], object received. null
refs
is a new attribute as I'm avoiding relationships right now, so they are always null. Seems like DataStore is interpreting "null" as an object for some reason.
Any tips on how to debug further?
@raelmiu
Look like the problem is in the way the transformer generates de mutation when both an id and the connected types are defined like this:
type TingRef
parentID: ID!
childID: ID!
parent: Ting! @connection(fields: ["parentID"])
child: Ting! @connection(fields: ["childID"])
}
As a quick fix, I got your schema working when I made this change to the TingRef
type:
- parent: Ting! @connection(fields: ["parentID"])
- child: Ting! @connection(fields: ["childID"])
+ parent: Ting @connection(fields: ["parentID"])
+ child: Ting @connection(fields: ["childID"])
Other minor things I changed:
owner
field to the Ting
model: owner: String
user
field in the UserTing
from Ting
to User
I hope this helps, I'll be bringing this up to the team to see how we can reduce these friction points.
Hi again @manueliglesias,
It's possible that this work around could work. But like I wrote in the comment above (https://github.com/aws-amplify/amplify-js/issues/4853#issuecomment-591473816) I can no longer sync any data from dynamoDb, so any API changes are unknowable.
Are datastore APIs extremely fragile to update or have I found some edge case here?
hey @raelmiu
Would it be possible that you clear all items in your DynamoDB tables AND the device storage (IndexedDB if browser, AsyncStorage in React Native)?
You can find them in the AppSync console under the Data Sources section: (clicking the resource name will take you to the DynamoDB console where you can delete the items)
Please make sure to clear also the table with the _AmplifyDataStore-_ prefix, you'll see it in DynamoDB's console too
Are datastore APIs extremely fragile to update or have I found some edge case here?
It certainly is a tough problem and we are thinking hard about it. The main issue is that changes to the schema at the GraphQL level are not guaranteed to be valid in the context of a NoSQL database. (e.g. marking a previously optional field as required in the GraphQL schema while some of the items in DynamoDB don't have a value for that field would throw an error when executing the GraphQL query)
Typically you would handle those schema changes gradually while migrating the data, in dev cycles it might be reasonable to just start from scratch while you tune your schema.
Of course we would love to hear your ideas on how we could tackle this problem in the future. Let us know if my suggestion at least unblocks you to keep iterating.
Thanks for the response, while it is possible at this state. It worries me more than a little bit that API changes could kill my database. Simply better error messages could help here, since I could manually handle issues if I knew what they were.
For debugging purposes these are the API changes that lead to this problem:
@model
@auth(rules: [{ allow: owner }, { allow: groups, groups: ["admins"] }]) {
id: ID!
+ owner: String
createdAt: AWSDateTime
- references: [TingRef] @connection(keyName: "byChild", fields: ["id"])
- referencedBy: [TingRef] @connection(keyName: "byParent", fields: ["id"])
+ # references: [TingRef] @connection(keyName: "byChild", fields: ["id"])
+ # referencedBy: [TingRef] @connection(keyName: "byParent", fields: ["id"])
content: String!
+ refs: [String]
+ refBy: [String]
# S3Object: S3Object
access: [UserTing] @connection(keyName: "byUser", fields: ["id"])
}
Interestingly, I've checked the DynamoDb and references are always null
. But it still failing to sync. If I remove all my changes and then remove references
and referencedBy
it works.
Tried to update to the following and getting the same should be type type string[] recieved object null
error. This shouldn't be related to the original issue, so I'm having a hard time understanding how a null array of strings could present errors.
type Ting
@model
@auth(rules: [{ allow: owner }, { allow: groups, groups: ["admins"] }]) {
id: ID!
createdAt: AWSDateTime
test: [String]
# references: [TingRef] @connection(keyName: "byChild", fields: ["id"])
# referencedBy: [TingRef] @connection(keyName: "byParent", fields: ["id"])
content: String!
# S3Object: S3Object
access: [UserTing] @connection(keyName: "byUser", fields: ["id"])
}
The error Error: Field references should be of type string[], object received. null
originates in datastore.ts
on row 245. I can't debug this however, because there's a missing build script required to build /@aws-amplify packages.
Resolving as the original bug is resolved, @raelmiu Can you open up a new bug for your above comment?
Most helpful comment
I'm having a similar issue:
Besides using Vue instead of Angular, it's pretty much the same configuration. Same Amplify-CLI version, 4.13.1