{"record":{"id":"66260b942b4872dd","repo":"dgraph-io/dgraph","slug":"post-method-cannot-have-query-parameters-in-url","errorCode":null,"errorMessage":"POST method cannot have query parameters in url: %s","messagePattern":"POST method cannot have query parameters in url: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/schema/remote.go","lineNumber":30,"sourceCode":"\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/golang/glog\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/dgraph-io/gqlparser/v2/ast\"\n)\n\nfunc validateUrl(rawURL string) error {\n\tu, err := url.ParseRequestURI(rawURL)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif u.RawQuery != \"\" {\n\t\treturn fmt.Errorf(\"POST method cannot have query parameters in url: %s\", rawURL)\n\t}\n\treturn nil\n}\n\ntype IntrospectionRequest struct {\n\tQuery string `json:\"query\"`\n}\n\n// introspectRemoteSchema introspectes remote schema\nfunc introspectRemoteSchema(url string, headers http.Header) (*introspectedSchema, error) {\n\tif err := validateUrl(url); err != nil {\n\t\treturn nil, err\n\t}\n\tparam := &IntrospectionRequest{\n\t\tQuery: introspectionQuery,\n\t}\n\n\tbody, err := json.Marshal(param)","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/schema/remote.go#L12-L48","documentation":"Dgraph's remote schema introspection is performed with a POST request, so validateUrl rejects any URL containing a query string. If the rawURL supplied in the @custom directive (or remote schema config) has ?... parameters, validation fails before any network call. This keeps introspection requests canonical and cacheable.","triggerScenarios":"Configuring a @custom directive with a remote GraphQL URL like https://api.example.com/graphql?env=prod and running schema validation (validateUrl called via introspectRemoteSchema).","commonSituations":"Copying URLs from browsers that appended tracking/query params; putting API keys in the URL query string; environment selectors in URLs.","solutions":["Remove the query string from the remote URL and keep only the bare endpoint path","Move any parameters into HTTP headers via the forward/custom header configuration instead","If auth via query param is unavoidable, configure a proxy endpoint without query params"],"exampleFix":"// before\nurl: \"https://api.example.com/graphql?env=prod\"\n// after\nurl: \"https://api.example.com/graphql\"","handlingStrategy":"validation","validationCode":"function assertCleanUrl(u) {\n  const parsed = new URL(u)\n  if (parsed.search) throw new Error(`POST remote url must not have query params: ${u}`)\n}","typeGuard":"func hasNoRawQuery(rawURL string) bool {\n  u, err := url.ParseRequestURI(rawURL)\n  return err == nil && u.RawQuery == \"\"\n}","tryCatchPattern":"err := schema.ValidateCustom(dgSchema, gqlSchema)\nif err != nil && strings.Contains(err.Error(), \"cannot have query parameters\") {\n  log.Printf(\"strip query params from remote url: %v\", err)\n}","preventionTips":["Store bare endpoint URLs in directive configs","Pass auth/params via headers, not query strings","Validate URLs in CI before applying schema updates"],"tags":["graphql","remote-schema","url","validation","dgraph"],"backgroundTag":"invalid-remote-url","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}