{"record":{"id":"13052c84bac460f0","repo":"alibaba/nacos","slug":"physical-key-prefix-leaves-insufficient-room-for-a","errorCode":null,"errorMessage":"Physical key prefix leaves insufficient room for a SHA-256 digest","messagePattern":"Physical key prefix leaves insufficient room for a SHA-256 digest","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/model/NacosAiConfigKeyCodec.java","lineNumber":220,"sourceCode":"        }\n        return out;\n    }\n    \n    private static boolean hasReservedEncodedPrefix(String value) {\n        return value.regionMatches(true, 0, ENCODED_PREFIX, 0, ENCODED_PREFIX.length());\n    }\n    \n    private static String fitToLength(String candidate, int maxLength, String preservedPrefix) {\n        if (candidate == null) {\n            return null;\n        }\n        String prefix = preservedPrefix == null ? \"\" : preservedPrefix;\n        if (candidate.length() <= maxLength && !isHashedPhysicalKey(candidate, prefix)) {\n            return candidate;\n        }\n        String result = prefix + HASHED_PREFIX + sha256Hex(candidate);\n        if (result.length() > maxLength) {\n            throw new IllegalArgumentException(\n                \"Physical key prefix leaves insufficient room for a SHA-256 digest\");\n        }\n        return result;\n    }\n    \n    private static boolean isHashedPhysicalKey(String candidate, String preservedPrefix) {\n        if (candidate == null) {\n            return false;\n        }\n        String marker = (preservedPrefix == null ? \"\" : preservedPrefix) + HASHED_PREFIX;\n        if (candidate.length() != marker.length() + 64\n            || !candidate.regionMatches(true, 0, marker, 0, marker.length())) {\n            return false;\n        }\n        for (int i = marker.length(); i < candidate.length(); i++) {\n            if (Character.digit(candidate.charAt(i), 16) < 0) {\n                return false;\n            }","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/model/NacosAiConfigKeyCodec.java#L202-L238","documentation":"NacosAiConfigKeyCodec.fitToLength tried to apply the SHA-256 length-fallback (prefix + 'sha256.' + 64-char digest) but the result still exceeds maxLength. This means the preserved prefix is so long that even a 64-character hash cannot fit within the Nacos Config dataId limit.","triggerScenarios":"A physical key prefix (e.g. a long namespace or resource-type prefix) combined with the sha256 fallback exceeds MAX_DATA_ID_LENGTH (255) or the provided maxLength. Typically caused by deeply nested or overly verbose prefix construction.","commonSituations":"Custom namespace hierarchies or multi-tenant prefixes that are very long. Group/dataId templates that concatenate many segments. A change to the prefix scheme increased its length beyond the digest budget.","solutions":["Shorten the preservedPrefix or reduce the number of concatenated segments.","Hash more of the key (including part of the prefix) rather than preserving the full prefix in plaintext.","Increase maxLength if the storage backend supports a larger dataId (but 255 is the Nacos Config ceiling).","Redesign the key layout to use fewer characters for static prefix portions."],"exampleFix":"// before\nString prefix = \"ai_registry__production__my-very-long-tenant-identifier__\";\n// prefix + 'sha256.' + 64 chars > maxLength\n\n// after -- hash the tenant portion too\nString prefix = \"ai_registry__prod__\";\n// now prefix + sha256 digest fits within 255","handlingStrategy":"validation","validationCode":"// Before calling fitToLength indirectly via build*Group, check prefix length\nint digestBudget = prefix.length() + NacosAiConfigKeyCodec.HASHED_PREFIX.length() + 64;\nif (digestBudget > NacosAiConfigKeyCodec.MAX_DATA_ID_LENGTH) {\n    // shorten prefix or redesign key layout\n    prefix = shortenPrefix(prefix);\n}","typeGuard":"public static boolean prefixFitsSha256(String prefix, int maxLength) {\n    int needed = prefix.length()\n        + NacosAiConfigKeyCodec.HASHED_PREFIX.length() + 64;\n    return needed <= maxLength;\n}","tryCatchPattern":"try {\n    group = AgentSpecUtils.buildAgentSpecVersionGroup(name, version);\n} catch (IllegalArgumentException e) {\n    // prefix too long; hash more of the key or shorten the prefix\n    name = hashShortName(name);\n    group = AgentSpecUtils.buildAgentSpecVersionGroup(name, version);\n}","preventionTips":["Keep static key prefixes short to leave room for the SHA-256 fallback.","Design key layouts with the 255-char dataId limit in mind.","Test long resource names against the encoding pipeline."],"tags":["codec","config-key","sha256","length-limit","storage"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}