apollographql / apollo-kotlin

:rocket:  A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
https://www.apollographql.com/docs/kotlin
MIT License
3.73k stars 653 forks source link

[Android] Apollo Introspection JsonDecodingException with Hasura server #6127

Open javierpe opened 3 weeks ago

javierpe commented 3 weeks ago

Version

4.0.0

Summary

Hi, Im trying download schema from Hasura GraphQL but I get an exception.

My Apollo Gradle config:

apollo { service("service") { packageName.set("com.survey.graphql") generateKotlinModels.set(true) generateSourcesDuringGradleSync.set(true) generatedSchemaName.set("schema") introspection { schemaFile.set(file("src/main/graphql/schema.graphql")) endpointUrl.set("http://mgsurveys24.mgroup.com.mx:1337/v1/graphql") headers.put("x-hasura-admin-secret", "---") } } }

With terminal and graphqurl works fine: graphqurl http://mgsurveys24.mgroup.com.mx:1337/v1/graphql -H 'X-Hasura-Admin-Secret: ---' --introspect > schema.graphql

Steps to reproduce the behavior

./gradlew :network:impl:downloadServiceApolloSchemaFromIntrospection

Logs

Caused by: com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 611385: Expected valid boolean literal prefix, but had 'null' at path: $.data.__schema.directives[0].isRepeatable
JSON input: .....ue":null}],"isRepeatable":null},{"name":"skip","description".....
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(SourceFile:1)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(SourceFile:2)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StringJsonLexer.fail(SourceFile:601)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StringJsonLexer.fail$default(SourceFile:1)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StringJsonLexer.consumeBoolean(SourceFile:15)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StringJsonLexer.consumeBooleanLenient$kotlinx$serialization$json$internal$AbstractJsonLexer(SourceFile:11)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeBoolean(SourceFile:2)
        at com.apollographql.apollo.relocated.kotlinx.serialization.encoding.AbstractDecoder.decodeBooleanElement(SourceFile:1)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.RDirective$$serializer.deserialize(SourceFile:198)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue$1(SourceFile:26)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(SourceFile:8)
        at com.apollographql.apollo.relocated.kotlinx.serialization.internal.CollectionLikeSerializer.readElement(SourceFile:2)
        at com.apollographql.apollo.relocated.kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(SourceFile:9)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.OptionalSerializer.deserialize(SourceFile:240)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue$1(SourceFile:26)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(SourceFile:8)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.RSchema$$serializer.deserialize(SourceFile:121)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue$1(SourceFile:26)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(SourceFile:8)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.RData$$serializer.deserialize(SourceFile:113)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue$1(SourceFile:26)
        at com.apollographql.apollo.relocated.kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(SourceFile:3)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.REnvelope$$serializer.deserialize(SourceFile:106)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue$1(SourceFile:26)
        at com.apollographql.apollo.relocated.kotlinx.serialization.json.Json.decodeFromString(SourceFile:3)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.ast.introspection.Introspection.toIntrospectionSchema(SourceFile:503)
        at com.apollographql.apollo.relocated.com.apollographql.apollo.tooling.SchemaDownloader.download(SourceFile:3770)
        ... 124 more
BoD commented 3 weeks ago

Hi!

From the stacktrace, it looks like the server returns a null value for the field isRepeatable - which is not compliant with the GraphQL spec here.

If you're able, could you execute this query and paste the result?

query IntrospectionQuery {
  __schema {
    queryType { name }
    mutationType { name }
    subscriptionType { name }
    types {
      ...FullType
    }
    directives {
      name
      description
      locations
      args {
        ...InputValue
      }
      isRepeatable
    }
  }
}

fragment FullType on __Type {
  kind
  name
  description
  fields(includeDeprecated: true) {
    name
    description
    args {
      ...InputValue
    }
    type {
      ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
    ...InputValue
  }
  interfaces {
    ...TypeRef
  }
  enumValues(includeDeprecated: true) {
    name
    description
    isDeprecated
    deprecationReason
  }
  possibleTypes {
    ...TypeRef
  }
}

fragment InputValue on __InputValue {
  name
  description
  type { ...TypeRef }
  defaultValue
}

fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
              }
            }
          }
        }
      }
    }
  }
}
BoD commented 3 days ago

@javierpe Did you have a chance to execute the introspection query?