Amplify-cli: AWS Amplify GraphQL subscriptions fail with "Cannot return null for non-nullable type: 'AWSDateTime' within parent ... for createdAt/updatedAt"

Created on 9 Oct 2020  ·  16Comments  ·  Source: aws-amplify/amplify-cli

Describe the bug
Subscriptions are triggered correctly by fail to return any data because of null values for automatically created 'createAt' and 'updatedAt' fields.

To Reproduce

Expected behavior
Subscripts get triggered when new items are created but the returned object is null with the following errors:

"message: "Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Video' (/onCreateVideo/createdAt)"
"message: "Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Video' (/onCreateVideo/updatedAt)"

Code Snippet
graphQL schema is as follows - mostly automatically generated by Amplify scripts:

type Video 
@model 
@key(name: "byAlbum", fields: ["albumId"], queryField: "listVideosByAlbum")
@auth(rules: [
  {allow: owner},
  {allow: private, provider: iam}
]) {
    id: ID!
    albumId: ID!
    album: Album @connection(fields: ["albumId"])
    bucket: String!
    fullsize: VideoS3Info!
    thumbnail: VideoS3Info!
}

export const createVideo = /* GraphQL */ `
  mutation CreateVideo(
    $input: CreateVideoInput!
    $condition: ModelVideoConditionInput
  ) {
    createVideo(input: $input, condition: $condition) {
      id
      albumId
      bucket
      fullsize {
        key
        width
        height
      }
      thumbnail {
        key
        width
        height
      }
      createdAt
      updatedAt
      album {
        id
        name
        createdAt
        updatedAt
        owner
        videos {
          nextToken
        }
      }
      owner
    }
  }
`;

export const onCreateVideo = /* GraphQL */ `
  subscription OnCreateVideo($owner: String) {
    onCreateVideo(owner: $owner) {
      id
      albumId
      bucket
      fullsize {
        key
        width
        height
      }
      thumbnail {
        key
        width
        height
      }
      createdAt
      updatedAt
      album {
        id
        name
        createdAt
        updatedAt
        owner
        videos {
          nextToken
        }
      }
      owner
    }
  }
`;

And the React client code

useEffect(() => {

    let subscription
    async function setupSubscription() {
      const user = await Auth.currentAuthenticatedUser()
      subscription = API.graphql(graphqlOperation(subscriptions.onCreateVideo, { owner: user.username })).subscribe({
        next: (data) => {
          const video = data.value.data.onCreateVideo
          console.log(data)
          if (video == null) return
          if (video.albumId !== selectedSectionId) return
          setVideos(p => p.concat([video]))
        }
      })
    }

    setupSubscription()

    return () => subscription?.unsubscribe();
  }, [selectedSectionId])

Screenshots
image

What is Configured?
If applicable, please provide what is configured for Amplify CLI:

  • Which steps did you follow via Amplify CLI when configuring your resources.
  • Which resources do you have configured?

    • If applicable, please provide your aws-exports file:

const awsmobile = {
    "aws_project_region": "ap-southeast-2",
    "aws_cognito_identity_pool_id": "ap-southeast-2:1e784fe9-11d9-48b4-923c-fd1fc92452bb",
    "aws_cognito_region": "ap-southeast-2",
    "aws_user_pools_id": "ap-southeast-2_R1IG6XNDi",
    "aws_user_pools_web_client_id": "7u6ogv91ge55e8f2iuc0lhm0db",
    "oauth": {},
    "aws_mobile_analytics_app_id": "a9bbeba55f2b4c3c830792f3ecabac48",
    "aws_mobile_analytics_app_region": "us-west-2",
    "aws_appsync_graphqlEndpoint": "https://q6xoqjhvvvhnnlawjk42ffaysy.appsync-api.ap-southeast-2.amazonaws.com/graphql",
    "aws_appsync_region": "ap-southeast-2",
    "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
    "aws_user_files_s3_bucket": "rpmappe304a60a89a44621a16622245ad6fb5801950-demo",
    "aws_user_files_s3_bucket_region": "ap-southeast-2"
};
  • If applicable, provide more configuration data, for example for Amazon Cognito, run aws cognito-idp describe-user-pool --user-pool-id us-west-2_xxxxxx (Be sure to remove any sensitive data)
    N/A


Environment

  System:
    OS: macOS 10.15.7
    CPU: (8) x64 Intel(R) Core(TM) i7-1060NG7 CPU @ 1.20GHz
    Memory: 384.65 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.18.1 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - /usr/local/bin/npm
  Browsers:
    Chrome: 85.0.4183.121
    Safari: 14.0
  npmPackages:
    @auth0/auth0-spa-js: ^1.12.1 => 1.12.1 
    @brainhubeu/react-carousel: ^1.19.20 => 1.19.26 
    @date-io/moment: ^1.3.13 => 1.3.13 
    @emotion/core: ^10.0.35 => 10.0.35 
    @emotion/styled: ^10.0.27 => 10.0.27 
    @material-ui/core: ^4.11.0 => 4.11.0 
    @material-ui/icons: ^4.9.1 => 4.9.1 
    @material-ui/lab: ^4.0.0-alpha.56 => 4.0.0-alpha.56 
    @material-ui/pickers: ^3.2.10 => 3.2.10 
    @popperjs/core: ^2.5.2 => 2.5.3 
    @storybook/addon-a11y: ^5.3.19 => 5.3.21 
    @storybook/addon-actions: ^5.3.19 => 5.3.21 
    @storybook/addon-knobs: ^5.3.19 => 5.3.21 
    @storybook/addon-links: ^5.3.19 => 5.3.21 
    @storybook/addons: ^5.3.19 => 5.3.21 
    @storybook/preset-create-react-app: ^3.0.0 => 3.1.4 
    @storybook/react: ^5.3.19 => 5.3.21 
    @storybook/theming: ^5.3.19 => 5.3.21 
    @testing-library/jest-dom: ^5.11.4 => 5.11.4 
    @testing-library/react: ^11.0.4 => 11.0.4 
    @testing-library/user-event: ^12.1.6 => 12.1.6 
    @types/d3-geo: ^1.11.1 => 1.12.1 
    @types/jest: ^26.0.14 => 26.0.14 
    @types/js-cookie: ^2.2.6 => 2.2.6 
    @types/material-ui: ^0.21.8 => 0.21.8 
    @types/node: ^14.11.2 => 14.11.2 
    @types/react: ^16.9.49 => 16.9.50 
    @types/react-color: ^3.0.4 => 3.0.4 
    @types/react-dom: ^16.9.8 => 16.9.8 
    @types/react-redux: ^7.1.9 => 7.1.9 
    @types/react-router-config: ^5.0.1 => 5.0.1 
    @types/react-router-dom: ^5.1.5 => 5.1.5 
    @types/react-simple-maps: ^1.0.3 => 1.0.3 
    @types/react-slick: ^0.23.4 => 0.23.4 
    @types/recharts: ^1.8.13 => 1.8.16 
    @types/styled-components: ^5.1.3 => 5.1.3 
    @types/yup: ^0.29.3 => 0.29.7 
    @typescript-eslint/eslint-plugin: ^4.2.0 => 4.3.0 
    @typescript-eslint/parser: ^4.2.0 => 4.3.0 
    amazon-cognito-identity-js: ^4.4.0 => 4.4.0 
    animate.css: ^4.1.1 => 4.1.1 
    apexcharts: ^3.19.3 => 3.21.0 
    array-move: ^3.0.1 => 3.0.1 
    autoprefixer: ^10.0.0 => 10.0.1 
    autosuggest-highlight: ^3.1.1 => 3.1.1 
    aws-amplify: ^3.3.2 => 3.3.3 
    axios: ^0.20.0 => 0.20.0 
    axios-mock-adapter: ^1.18.2 => 1.18.2 
    babel-eslint: ^10.1.0 => 10.1.0 
    babel-plugin-transform-imports: ^2.0.0 => 2.0.0 
    babel-plugin-transform-remove-console: ^6.9.4 => 6.9.4 
    clsx: ^1.1.1 => 1.1.1 
    connected-react-router: ^6.8.0 => 6.8.0 
    d3-geo: ^2.0.1 => 2.0.1 
    date-fns: ^2.16.1 => 2.16.1 
    downshift: ^6.0.6 => 6.0.6 
    draft-js: ^0.11.7 => 0.11.7 
    eslint: ^6.6.0 => 6.8.0 
    eslint-config-prettier: ^6.12.0 => 6.12.0 
    eslint-config-react-app: ^5.2.1 => 5.2.1 
    eslint-plugin-flowtype: ^5.2.0 => 5.2.0 
    eslint-plugin-import: ^2.22.0 => 2.22.1 
    eslint-plugin-prettier: ^3.1.4 => 3.1.4 
    eslint-plugin-react: ^7.21.2 => 7.21.2 
    eslint-plugin-react-hooks: ^4.1.2 => 4.1.2 
    firebase: ^7.21.1 => 7.22.0 
    flag-icon-css: ^3.5.0 => 3.5.0 
    formik: ^2.1.5 => 2.1.7 
    husky: ^4.2.3 => 4.3.0 
    intl-messageformat: ^9.3.9 => 9.3.9 
    intl-messageformat-parser: ^6.0.7 => 6.0.8 
    jss: ^10.4.0 => 10.4.0 
    jss-extend: ^6.2.0 => 6.2.0 
    jss-rtl: ^0.3.0 => 0.3.0 
    lint-staged: ^10.0.8 => 10.4.0 
    lodash: ^4.17.20 => 4.17.20 
    match-sorter: ^4.2.1 => 4.2.1 
    material-table: ^1.69.0 => 1.69.1 
    material-ui-popup-state: ^1.6.1 => 1.6.1 
    moment: ^2.29.0 => 2.29.0 
    namor: ^2.0.2 => 2.0.2 
    notistack: ^1.0.0 => 1.0.0 
    npm-run-all: ^4.1.5 => 4.1.5 
    postcss-import: ^12.0.1 => 12.0.1 
    prettier: ^2.1.2 => 2.1.2 
    prism-react-renderer: ^1.1.1 => 1.1.1 
    prop-types: ^15.7.2 => 15.7.2 
    purgecss: ^1.4.2 => 1.4.2 
    raw-loader: ^4.0.1 => 4.0.1 
    rc-queue-anim: ^1.8.3 => 1.8.5 
    react: ^16.13.1 => 16.13.1 
    react-apexcharts: ^1.3.7 => 1.3.7 
    react-autosuggest: ^10.0.2 => 10.0.2 
    react-beautiful-dnd: ^13.0.0 => 13.0.0 
    react-big-calendar: ^0.28.0 => 0.28.0 
    react-bottom-scroll-listener: ^4.1.0 => 4.1.0 
    react-chat-window: ^1.2.1 => 1.2.1 
    react-circular-progressbar: ^2.0.3 => 2.0.3 
    react-code-input: ^3.10.0 => 3.10.0 
    react-color: ^2.18.1 => 2.18.1 
    react-daypicker: ^3.0.10 => 3.0.10 
    react-dnd: ^11.1.3 => 11.1.3 
    react-dnd-html5-backend: ^11.1.3 => 11.1.3 
    react-dom: ^16.13.1 => 16.13.1 
    react-draft-wysiwyg: ^1.14.5 => 1.14.5 
    react-draggable: ^4.4.3 => 4.4.3 
    react-dropzone: ^11.2.0 => 11.2.0 
    react-google-maps: ^9.4.5 => 9.4.5 
    react-image-timeline: ^3.2.13 => 3.2.13 
    react-images: ^1.1.7 => 1.1.7 
    react-intl: ^5.8.2 => 5.8.4 
    react-notifications-component: ^2.4.1 => 2.4.1 
    react-number-format: ^4.4.1 => 4.4.1 
    react-perfect-scrollbar: ^1.5.8 => 1.5.8 
    react-photo-gallery: ^8.0.0 => 8.0.0 
    react-player: ^2.6.2 => 2.6.2 
    react-popper: ^2.2.3 => 2.2.3 
    react-redux: ^7.2.1 => 7.2.1 
    react-ripples: ^2.2.1 => 2.2.1 
    react-router-config: ^5.1.1 => 5.1.1 
    react-router-dom: ^5.2.0 => 5.2.0 
    react-router-redux: ^4.0.8 => 4.0.8 
    react-scripts: ^3.4.3 => 3.4.3 
    react-select: ^3.1.0 => 3.1.0 
    react-share: ^4.2.1 => 4.3.0 
    react-simple-maps: ^2.1.2 => 2.1.2 
    react-slick: ^0.27.11 => 0.27.11 
    react-sortable-hoc: ^1.11.0 => 1.11.0 
    react-spring: ^8.0.27 => 8.0.27 
    react-svg-piechart: ^2.4.1 => 2.4.1 
    react-swipeable-views: ^0.13.9 => 0.13.9 
    react-table: 6.10.3 => 6.10.3 
    react-text-mask: ^5.4.3 => 5.4.3 
    react-toastify: ^6.0.8 => 6.0.8 
    react-tooltip: ^4.2.7 => 4.2.10 
    react-transition-group: ^4.4.1 => 4.4.1 
    react-virtualized: ^9.22.2 => 9.22.2 
    react-window: ^1.8.5 => 1.8.5 
    recharts: ^1.8.5 => 1.8.5 
    redux: ^4.0.5 => 4.0.5 
    redux-thunk: ^2.3.0 => 2.3.0 
    slick-carousel: ^1.8.1 => 1.8.1 
    storybook-addon-material-ui: ^0.9.0-alpha.21 => 0.9.0-alpha.21 
    styled-components: ^5.2.0 => 5.2.0 
    tslint: ^6.1.2 => 6.1.3 
    tslint-react: ^5.0.0 => 5.0.0 
    typescript: ^3.8.3 => 3.9.7 
    use-url-search-params: ^2.3.13 => 2.3.13 
    velocity-animate: ^1.5.2 => 1.5.2 
    velocity-react: ^1.4.3 => 1.4.3 
    yup: ^0.29.3 => 0.29.3 
  npmGlobalPackages:
    @aws-amplify/cli: 4.29.4
    amplify-cli: 1.0.0
    npm: 6.14.8
    typescript: 4.0.3
    yarn: 1.22.10

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
N/A

graphql-transformer pending-response question

Most helpful comment

I had the similar problem and what I realised is that mutation which in fact triggers the subscription has to have the same response fields as the ones specified for the subscription response. This way it works for me.

All 16 comments

@duncangroenewald what version of Amplify CLI do you have installed?

Could you update your Video type to the following and see if the error goes away

type Video 
@model 
@key(name: "byAlbum", fields: ["albumId"], queryField: "listVideosByAlbum")
@auth(rules: [
  {allow: owner},
  {allow: private, provider: iam}
]) {
    id: ID!
    albumId: ID!
    album: Album @connection(fields: ["albumId"])
    bucket: String!
    fullsize: VideoS3Info!
    thumbnail: VideoS3Info!
    createdAt: AWSDateTime
    updatedAt:AWSDateTime
}

I am getting a similar issue with a connection to a model not allowing me to grab the nested values

type User @model(subscriptions: null) {
  id: ID!
  firstName: String!
  lastName: String!
  email: String!
  messages: [Message] @connection(keyName: "byAuthor", fields: ["id"])
}

type Message @model(subscriptions: null, queries: null) {
  id: ID!
  content: String!
  authorId: ID!
  author: User! @connection(fields: ["authorId"])
  conversationId: ID!
}

type Subscription {
  onCreateMessage(conversationId: ID!): Message @aws_subscribe(mutations: ["createMessage"])
}

and I get the error:
"Cannot return null for non-nullable type: 'User' within parent 'Message' (/onCreateMessage/author)"

@LoganArnett It looks like your schema expect the author to be non-nullable, and the Message does not seem to have an valid author. This could either be because the createMessage passed an non-existent authorId or the Author with that authorId was delete from User table.

I am not sure what happened but I edited another model and pushed and it worked so maybe somehow I was out of sync, thanks @yuth

Please feel free to comment here if you need any further clarification

@duncangroenewald what version of Amplify CLI do you have installed?

Could you update your Video type to the following and see if the error goes away

type Video 
@model 
@key(name: "byAlbum", fields: ["albumId"], queryField: "listVideosByAlbum")
@auth(rules: [
  {allow: owner},
  {allow: private, provider: iam}
]) {
    id: ID!
    albumId: ID!
    album: Album @connection(fields: ["albumId"])
    bucket: String!
    fullsize: VideoS3Info!
    thumbnail: VideoS3Info!
    createdAt: AWSDateTime
    updatedAt:AWSDateTime
}

@yuth - sorry for the delayed response been tied down with some other things. I will give that a try and let you know how it goes. Thanks

BTW will these still be auto-populated by AppSync if I defined them in the schema? I guess I'll find out...

@yuth - I just tried that but the returned object is still null.

If I turn AppSync logging on I should be able to see the error in CloudWatch right?

Hmm nothing to see in CloudWatch!

But no errors reported now in the browser console.

image

Amplify 4.29.8

Could you try running the subscription and mutation in the AppSync console. This should make it easier to debug as you can narrow down if the problem is in AppSync resolver or in the Javascript side of things

BTW will these still be auto-populated by AppSync if I defined them in the schema? I guess I'll find out...

It should add the autopupulate createdAt and updatedAt if no value was passed in the input

This subscription seems to work fine in the console:

subscription MySubscription {
  onCreateVideo {
    id
      bucket
      key
      sessionDate
      isReviewed
      reviewedBy
      reviewDate
      title
      comments
      sessionTypeID
      activityTypeID
      modeID
      genderID
      ageGroupID
      weightCategoryID
      athletes {
        items {
          id
          createdAt
          updatedAt
        }
        nextToken
      }
      createdAt
      updatedAt
      sessionType {
        id
        name
        activityTypes {
          nextToken
        }
        modes {
          nextToken
        }
        createdAt
        updatedAt
        videos {
          nextToken
        }
      }
      owner
  }
}

However the definition is slightly different to the one used in the app which has the $owner parameter - and I am not sure I understand the distinction. I an going to try a customised subscription without the $owner parameter in the app.

export const onCreateVideo = /* GraphQL */ `
  subscription OnCreateVideo($owner: String) {
    onCreateVideo(owner: $owner) {
      id
      bucket
      key
      sessionDate
      isReviewed
      reviewedBy
      reviewDate
      title
      comments
      sessionTypeID
      activityTypeID
      modeID
      genderID
      ageGroupID
      weightCategoryID
      athletes {
        items {
          id
          createdAt
          updatedAt
        }
        nextToken
      }
      createdAt
      updatedAt
      sessionType {
        id
        name
        activityTypes {
          nextToken
        }
        modes {
          nextToken
        }
        createdAt
        updatedAt
        videos {
          nextToken
        }
      }
      owner
    }
  }
`;

So in the end I got rid of the $owner in the schema definition - which fixed the problem. I guess it wasn't happy that I was not passing in the owner parameter so couldn't send the data but could still trigger the event.

I'm having a similar issue with subscriptions. However, it isn't working in the AppSync console either.

This is the error:

"data": {
    "onUpdateLead": null
  },
  "errors": [
    {
      "message": "Cannot return null for non-nullable type: 'String' within parent 'Lead' (/onUpdateLead/formId)",
      "path": [
        "onUpdateLead",
        "formId"
      ]
    },
    {
      "message": "Cannot return null for non-nullable type: 'DeliveryStatus' within parent 'Lead' (/onUpdateLead/deliveryStatus)",
      "path": [
        "onUpdateLead",
        "deliveryStatus"
      ]
    }
  ]

These is the error I get in my app when a subscription returns. Also, just like in the AppSync console message no object is being returned.

0: Object { message: "Cannot return null for non-nullable type: 'String' within parent 'Lead' (/onUpdateLead/formId)", path: (2) […] }
1: Object { message: "Cannot return null for non-nullable type: 'String' within parent 'Lead' (/onUpdateLead/pageId)", path: (2) […] }
2: Object { message: "Cannot return null for non-nullable type: 'Status' within parent 'Lead' (/onUpdateLead/status)", path: (2) […] }
3: Object { message: "Cannot return null for non-nullable type: 'DeliveryStatus' within parent 'Lead' (/onUpdateLead/deliveryStatus)", path: (2) […] }
4: Object { message: "Cannot return null for non-nullable type: 'ID' within parent 'Lead' (/onUpdateLead/mappingDataID)", path: (2) […] 
5: Object { message: "Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Lead' (/onUpdateLead/createdAt)", path: (2) […] 
6: Object { message: "Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Lead' (/onUpdateLead/updatedAt)", path: (2) […] }

If I don't include any of the non-nullable fields in the return of the subscription the ID returns but any other field returns null. Why is that?

Schema

type Lead
  @model
  @key(name: "byMappingData", fields: ["mappingDataID"])
  @auth(
    rules: [
      { allow: private, operations: [update, read] }
      { allow: private, provider: iam, operations: [create, read, update] }
    ]
  ) {
  id: ID!
  formId: String!
  pageId: String!
  processedLeadData: String
  status: Status!
  deliveryStatus: DeliveryStatus!
  zohoResponse: String
  createdTime: String
  fbLeadId: String
  rawLeadData: [FieldData]
  mappingDataID: ID!
  submitDataToZoho: Boolean
  mappingData: MappingData @connection(fields: ["mappingDataID"])
}

This is the subscription I'm using:

export const onUpdateLead = /* GraphQL */ `
  subscription OnUpdateLead {
    onUpdateLead {
      id
      formId
      pageId
      processedLeadData
      status
      deliveryStatus
      zohoResponse
      createdTime
      fbLeadId
      rawLeadData {
        name
        values
      }
      mappingDataID
      submitDataToZoho
      createdAt
      updatedAt
      mappingData {
        id
        formName
        formId
        pageId
        mappingInfo {
          forcedFields
        }
        rawLeadFields {
          key
          label
          type
          id
          conditional_questions_group_id
        }
        status
        formCreatedTime
        deliveryStatus
        errors
        campaignName
        campaignId
        archived
        createdAt
        updatedAt
        leads {
          nextToken
        }
      }
    }
  }
`;

When I use the updateLead mutation it returns whatever fields are selected to be returned. I don't understand why the subscription isn't doing this. Am I missing something?

I'm using 4.30.0 of the Amplify CLI.

I had the similar problem and what I realised is that mutation which in fact triggers the subscription has to have the same response fields as the ones specified for the subscription response. This way it works for me.

I've run into this issue and have tried 10 different ways to solve it. my object returned was:

type Checkin
  @model
  @searchable
  @key(name: "byUserId", fields: ["userId"], queryField: "checkinByUserId")
  @auth(
    rules: [
      { allow: owner }
      { allow: private, operations: [read] }
      { allow: private, provider: iam, operations: [create, read, update] }
    ]
  ) {
  comment: String
  createdAt: AWSDateTime!
  time: AWSDateTime!
  id: ID!
  userId: ID!
  team: Team @connection(name: "CheckinOnTeam")
  game: Game! @connection(name: "CheckinsOnGame")
  updatedAt: AWSDateTime!
  user: User! @connection(name: "CheckinOnUser")
  venue: Venue @connection(name: "CheckinOnVenue")
  isPrivate: Boolean
  atHome: Boolean
}

and I have a mutation:

updateCheckinStats(
    action: String!
    checkinId: String!
    numCheers: Int
    numComments: Int
  ): Checkin! @function(name: "updateCheckinStats-${env}")

When I run the query in the api console it still get:

Cannot return null for non-nullable type: 'Game' within parent 'Checkin' (/updateCheckinStats/game)
Cannot return null for non-nullable type: 'User' within parent 'Checkin' (/updateCheckinStats/user)

I've punted on it and just having it return boolean if the update was successful but this is super annoying.

I had the similar problem and what I realised is that mutation which in fact triggers the subscription has to have the same response fields as the ones specified for the subscription response. This way it works for me.

I was just trying to figure out the same and it looks like @aleksvidak was correct. It is not an expected behaviour, but works, so thanks 👍

BTW it works correctly if you use amplify mock to test localy 🤷‍♂️

I had the similar problem and what I realised is that mutation which in fact triggers the subscription has to have the same response fields as the ones specified for the subscription response. This way it works for me.

This worked for me as well.... So strange...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adriatikgashi picture adriatikgashi  ·  3Comments

MageMasher picture MageMasher  ·  3Comments

zjullion picture zjullion  ·  3Comments

nicksmithr picture nicksmithr  ·  3Comments

kangks picture kangks  ·  3Comments