{"record":{"id":"62a3f5d43b806fea","repo":"dgraph-io/dgraph","slug":"unavailable-server-not-ready","errorCode":null,"errorMessage":"Unavailable: Server not ready.","messagePattern":"Unavailable: Server not ready\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"graphql/admin/admin.go","lineNumber":769,"sourceCode":"\t\tWithQueryResolver(\"health\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(resolveHealth)\n\t\t}).\n\t\tWithQueryResolver(\"state\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(resolveState)\n\t\t}).\n\t\tWithQueryResolver(\"config\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(resolveGetConfig)\n\t\t}).\n\t\tWithQueryResolver(\"listBackups\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(resolveListBackups)\n\t\t}).\n\t\tWithQueryResolver(\"task\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(resolveTask)\n\t\t}).\n\t\tWithQueryResolver(\"getGQLSchema\", func(q schema.Query) resolve.QueryResolver {\n\t\t\treturn resolve.QueryResolverFunc(\n\t\t\t\tfunc(ctx context.Context, query schema.Query) *resolve.Resolved {\n\t\t\t\t\treturn &resolve.Resolved{Err: errors.Errorf(errMsgServerNotReady), Field: q}\n\t\t\t\t})\n\t\t}).\n\t\tWithMutationResolver(\"updateGQLSchema\", func(m schema.Mutation) resolve.MutationResolver {\n\t\t\treturn resolve.MutationResolverFunc(\n\t\t\t\tfunc(ctx context.Context, m schema.Mutation) (*resolve.Resolved, bool) {\n\t\t\t\t\treturn &resolve.Resolved{Err: errors.Errorf(errMsgServerNotReady), Field: m},\n\t\t\t\t\t\tfalse\n\t\t\t\t})\n\t\t})\n\tfor gqlMut, resolver := range adminMutationResolvers {\n\t\t// gotta force go to evaluate the right function at each loop iteration\n\t\t// otherwise you get variable capture issues\n\t\tfunc(f resolve.MutationResolver) {\n\t\t\trf.WithMutationResolver(gqlMut, func(m schema.Mutation) resolve.MutationResolver {\n\t\t\t\treturn f\n\t\t\t})\n\t\t}(resolver)\n\t}","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/admin/admin.go#L751-L787","documentation":"The admin GraphQL server registers placeholder resolvers that return errMsgServerNotReady until the admin schema has been loaded from storage. Any query hitting a not-yet-registered field (here the getGQLSchema query) is answered with this Unavailable error instead of executing. It signals the server is up but the admin GraphQL layer is not initialized yet.","triggerScenarios":"Sending a GraphQL getGQLSchema query to the /admin endpoint before resetSchema/NewServers has finished loading the stored admin schema, i.e. during Dgraph startup or while a schema reset is in flight.","commonSituations":"Health probes or automation scripts hitting /admin immediately after process start; race between server readiness and schema lazy-load; a fresh Dgraph instance where the admin schema hasn't been replayed yet.","solutions":["Wait for the server to report ready (or retry the query with backoff) before calling getGQLSchema.","Check that the GraphQL schema stored in Dgraph (for the namespace) is intact so lazy loading completes.","If it persists after startup, inspect logs for errors in lazyLoadSchema/getCurrentGraphQLSchema that blocked schema registration."],"exampleFix":"// before: curl /admin immediately after start\ncurl -X POST localhost:8080/admin -d '{getGQLSchema{schema}}'\n// after: retry until ready\nuntil curl -sf -X POST localhost:8080/admin -d '{__typename}' ; do sleep 1; done\ncurl -X POST localhost:8080/admin -d '{getGQLSchema{schema}}'","handlingStrategy":"retry","validationCode":"// wait until admin endpoint responds before real queries\nasync function adminReady(url) {\n  for (let i = 0; i < 30; i++) {\n    try { const r = await fetch(url, {method:'POST', body:'{__typename}', headers:{'Content-Type':'application/graphql'}}); if (r.ok) return true; } catch {}\n    await new Promise(r => setTimeout(r, 1000));\n  }\n  return false;\n}","typeGuard":null,"tryCatchPattern":"try { await runAdminQuery(); } catch (e) { if (String(e).includes('Server not ready')) { await sleep(1000); /* retry */ } else throw e; }","preventionTips":["Gate admin automation on a readiness probe, not on port availability","Use exponential backoff on /admin calls during startup","Monitor logs for lazy-load failures if not-ready persists"],"tags":["graphql","admin","server-not-ready","startup"],"backgroundTag":"server-not-ready","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}