{"record":{"id":"227e896269290084","repo":"theonedev/onedev","slug":"unexpected-query-params","errorCode":null,"errorMessage":"Unexpected query params: ","messagePattern":"Unexpected query params: ","errorType":"validation","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/ParamCheckFilter.java","lineNumber":48,"sourceCode":"\t\n\t@Override\n\tpublic void filter(ContainerRequestContext requestContext) throws IOException {\n\t\tSet<String> definedQueryParams = new HashSet<>();\n\t\tSet<String> requiredQueryParams = new HashSet<>();\n\t\tfor (Parameter param: resourceInfo.getResourceMethod().getParameters()) {\n\t\t\tQueryParam queryParam = param.getAnnotation(QueryParam.class);\n\t\t\tif (queryParam != null) {\n\t\t\t\tdefinedQueryParams.add(queryParam.value());\n\t\t\t\tif (isRequired(param)) \n\t\t\t\t\trequiredQueryParams.add(queryParam.value());\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (resourceInfo.getResourceClass() != TriggerJobResource.class) {\n\t\t\tSet<String> suppliedQueryParams = new HashSet<>(uriInfo.getQueryParameters().keySet());\n\t\t\tsuppliedQueryParams.removeAll(definedQueryParams);\n\t\t\tif (!suppliedQueryParams.isEmpty()) \n\t\t\t\tthrow new NotAcceptableException(\"Unexpected query params: \" + suppliedQueryParams);\n\t\t}\n\n\t\trequiredQueryParams.removeAll(uriInfo.getQueryParameters().keySet());\n\t\tif (!requiredQueryParams.isEmpty()) \n\t\t\tthrow new NotAcceptableException(\"Missing query params: \" + requiredQueryParams);\n\t}\n\n\tpublic static boolean isRequired(Parameter param) {\n\t\treturn param.getType().isPrimitive() \n\t\t\t\t|| param.getAnnotation(NotNull.class) != null \n\t\t\t\t|| param.getAnnotation(NotEmpty.class) != null \n\t\t\t\t|| param.getAnnotation(Size.class)!=null && param.getAnnotation(Size.class).min()>0;\n\t}\n\t\n}\n","sourceCodeStart":30,"sourceCodeEnd":64,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/ParamCheckFilter.java#L30-L64","documentation":"OneDev's ParamCheckFilter (a JAX-RS container request filter) rejects REST API calls whose query string contains parameters not declared via @QueryParam on the target resource method. This is an intentional strictness guard: unknown query params surface immediately as HTTP 406 NotAcceptableException instead of being silently ignored. Only the TriggerJobResource endpoint is exempt.","triggerScenarios":"Calling any OneDev REST resource (other than TriggerJobResource) with a query parameter the invoked method does not define — e.g. appending ?page=2 to an endpoint with no such @QueryParam, or a typo like ?projectID= instead of ?projectId=. The filter throws when suppliedQueryParams minus definedQueryParams is non-empty.","commonSituations":"Reusing a query string copied from a different endpoint's docs; adding params supported in a different OneDev version; typo'd parameter names; generic HTTP clients appending defaults like ?format=json the endpoint never defined.","solutions":["Remove the unknown query parameter(s) named in the message from the request URL","Check the OneDev REST API docs (or the resource class source) for the exact @QueryParam names the endpoint defines","Fix typos in parameter names (the set in the message lists the offending names)","If a parameter used to work, verify server version — the endpoint signature may have changed between versions"],"exampleFix":"// before\nGET /api/projects?name=app&pageSize=10   // endpoint has no pageSize @QueryParam\n// after\nGET /api/projects?name=app               // or use the endpoint's actual paging param","handlingStrategy":"validation","validationCode":"const url = new URL(requestUrl);\nconst allowed = ['name','offset']; // @QueryParam names from endpoint docs/source\nconst unknown = [...url.searchParams.keys()].filter(k => !allowed.includes(k));\nif (unknown.length) throw new Error(`Unexpected query params: ${unknown}`);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(url);\n  if (res.status === 406) {\n    const msg = await res.text();\n    const unknown = msg.match(/Unexpected query params: \\[([^\\]]+)\\]/)?.[1];\n    // strip the offending params and retry\n  }\n} catch (e) { /* handle network error */ }","preventionTips":["Build query strings from the endpoint's documented parameter list only","Use swagger-generated/official API clients instead of hand-built URLs","Log full request URLs so unexpected params are visible when a 406 occurs"],"tags":["rest","query-params","http-406","validation"],"backgroundTag":"invalid-query-parameter","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}