{"record":{"id":"e4a852de9a493bbd","repo":"alibaba/nacos","slug":"400","errorCode":"400","errorMessage":"Unsupported ARD orderBy field: {field}","messagePattern":"Unsupported ARD orderBy field: (.+?)","errorType":"validation","errorClass":"NacosApiException","httpStatus":null,"severity":"error","filePath":"ai-registry-adaptor/src/main/java/com/alibaba/nacos/airegistry/service/ard/ArdSearchServiceImpl.java","lineNumber":604,"sourceCode":"        return Math.min(pageSize, MAX_LIST_PAGE_SIZE);\n    }\n    \n    private void parseOrderBy(String orderBy, ListContext context) throws NacosApiException {\n        context.orderBy = \"updatedAt\";\n        context.orderDescending = true;\n        if (StringUtils.isBlank(orderBy)) {\n            return;\n        }\n        String[] parts = orderBy.trim().split(\"\\\\s+\");\n        String field = parts[0];\n        if (\"name\".equalsIgnoreCase(field)) {\n            field = \"displayName\";\n        } else if (\"updated_at\".equalsIgnoreCase(field)) {\n            field = \"updatedAt\";\n        }\n        if (!\"displayName\".equals(field) && !\"updatedAt\".equals(field)\n            && !\"identifier\".equals(field)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM,\n                ErrorCode.PARAMETER_VALIDATE_ERROR, \"Unsupported ARD orderBy field: \" + field);\n        }\n        context.orderBy = field;\n        context.orderDescending = parts.length > 1 && \"desc\".equalsIgnoreCase(parts[1]);\n    }\n    \n    private Map<String, List<String>> normalizeFilter(ArdSearchQuery query)\n        throws NacosApiException {\n        Map<String, List<String>> result = new LinkedHashMap<>();\n        if (query.getFilter() != null && !query.getFilter().isEmpty()) {\n            for (Map.Entry<String, Object> entry : query.getFilter().entrySet()) {\n                addFilter(result, entry.getKey(),\n                    normalizeFilterValues(entry.getKey(), entry.getValue()));\n            }\n        }\n        if (query.getFilters() == null || query.getFilters().isEmpty()) {\n            return result;\n        }","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai-registry-adaptor/src/main/java/com/alibaba/nacos/airegistry/service/ard/ArdSearchServiceImpl.java#L586-L622","documentation":"Thrown by parseOrderBy() when the orderBy field (after aliasing) is not one of the allowed sort keys. Accepted: displayName (alias 'name'), updatedAt (alias 'updated_at'), or identifier. Any other first token yields PARAMETER_VALIDATE_ERROR (HTTP 400). The optional second token may be 'desc' (case-insensitive) for descending order.","triggerScenarios":"Sending orderBy=createdAt, orderBy=version, orderBy=status, or orderBy=relevance. The aliasing only maps 'name'->'displayName' and 'updated_at'->'updatedAt'; everything else must already be the canonical internal name.","commonSituations":"Client assumes more sortable fields than supported; forwards a database column name not exposed by ARD; uses a camelCase field that isn't in the allowlist; expects createdAt to be sortable when only updatedAt is.","solutions":["Use orderBy one of: name, updated_at, displayName, updatedAt, or identifier.","Append ' desc' for descending order (e.g. 'updatedAt desc'); ascending is the default otherwise.","If you need to sort by an unsupported field, request it as a feature and sort client-side in the meantime.","Leave orderBy unset to accept the server default (updatedAt desc)."],"exampleFix":"// before\nreq.setOrderBy(\"createdAt\");\n\n// after\nreq.setOrderBy(\"updatedAt desc\");\n// or: \"name\", \"updated_at\", \"identifier\"","handlingStrategy":"validation","validationCode":"private static final Set<String> ORDER_BY_FIELDS =\n    Set.of(\"displayName\", \"updatedAt\", \"identifier\");\nprivate static final Map<String,String> ORDER_BY_ALIASE = Map.of(\n    \"name\", \"displayName\", \"updated_at\", \"updatedAt\");\n\npublic String normalizeOrderBy(String orderBy) {\n    if (orderBy == null || orderBy.trim().isEmpty()) return \"updatedAt\";\n    String[] parts = orderBy.trim().split(\"\\\\s+\");\n    String field = ORDER_BY_ALIASE.getOrDefault(parts[0].toLowerCase(), parts[0]);\n    if (!ORDER_BY_FIELDS.contains(field)) {\n        throw new IllegalArgumentException(\n            \"orderBy must be one of \" + ORDER_BY_FIELDS + \" (aliases: name, updated_at)\");\n    }\n    return field;\n}","typeGuard":"boolean isValidOrderBy(String orderBy) {\n    if (orderBy == null || orderBy.trim().isEmpty()) return true;\n    String f = orderBy.trim().split(\"\\\\s+\")[0].toLowerCase();\n    return Set.of(\"name\",\"updated_at\",\"displayname\",\"updatedat\",\"identifier\").contains(f);\n}","tryCatchPattern":null,"preventionTips":["Restrict the orderBy picker UI to the three supported fields plus their aliases.","Leave orderBy unset to accept the default (updatedAt desc).","Unit-test orderBy normalization against the server allowlist."],"tags":["ard","ai-registry","list","order-by","parameter-validation"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}