{"record":{"id":"2a37e7852c9f4754","repo":"prestodb/presto","slug":"cannot-parse-distinct-type-definition-s-expecte-2a37e7","errorCode":null,"errorMessage":"Cannot parse distinct type definition(%s), expected ',' after position %s","messagePattern":"Cannot parse distinct type definition\\((.+?)\\), expected ',' after position (.+?)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/type/TypeSignature.java","lineNumber":321,"sourceCode":"            this.distinctType = distinctType;\n        }\n\n        private static Optional<QualifiedObjectName> parseParentName(String s)\n        {\n            return s.equals(\"null\") ? Optional.empty() : Optional.of(QualifiedObjectName.valueOf(s));\n        }\n\n        private static DistinctTypeParsingData parse(String signature, int startIndex)\n        {\n            int openBracketIndex = signature.indexOf(\"{\", startIndex);\n            if (openBracketIndex == -1) {\n                throw new IllegalStateException(format(\"Cannot parse distinct type definition(%s), expected '{' after position %s\", signature, startIndex));\n            }\n            QualifiedObjectName name = QualifiedObjectName.valueOf(signature.substring(startIndex, openBracketIndex));\n\n            int firstCommaIndex = signature.indexOf(\", \", openBracketIndex);\n            if (firstCommaIndex == -1) {\n                throw new IllegalStateException(format(\"Cannot parse distinct type definition(%s), expected ',' after position %s\", signature, openBracketIndex));\n            }\n            TypeSignature baseType = TypeSignature.parseTypeSignature(signature.substring(openBracketIndex + 1, firstCommaIndex));\n\n            int secondCommaIndex = signature.indexOf(\", \", firstCommaIndex + 2);\n            if (secondCommaIndex == -1) {\n                throw new IllegalStateException(format(\"Cannot parse distinct type definition(%s), expected ',' after position %s\", signature, secondCommaIndex));\n            }\n            boolean isOrderable = parseBoolean(signature.substring(firstCommaIndex + 2, secondCommaIndex));\n\n            int thirdCommaIndex = signature.indexOf(\", [\", secondCommaIndex + 2);\n            if (thirdCommaIndex == -1) {\n                throw new IllegalStateException(format(\"Cannot parse distinct type definition(%s), expected '[' after position %s\", signature, secondCommaIndex));\n            }\n            Optional<QualifiedObjectName> topMostAncestor = parseParentName(signature.substring(secondCommaIndex + 2, thirdCommaIndex));\n\n            int endIndex = signature.indexOf(\"]}\", thirdCommaIndex + 3);\n            int position = thirdCommaIndex + 3;\n            List<QualifiedObjectName> otherAncestors = new ArrayList<>();","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/type/TypeSignature.java#L303-L339","documentation":"Thrown by DistinctTypeParsingData.parse when the serialized distinct type signature lacks the first \", \" separator after the '{' that opens the definition. The parser expects 'name{baseType, ...' and cannot find the comma following the base type. It indicates a malformed distinct-type signature string.","triggerScenarios":"Parsing a distinct type signature where the base type is not followed by ', ' — e.g. 'name{bigint true, []}' or 'name{bigint}' with the orderable/ancestors fields missing entirely.","commonSituations":"Manually constructing signatures for tests, a signature truncated after the base type, connectors or plugins that serialize distinct types with a non-standard separator (e.g. single comma without space — the parser searches for \", \" exactly).","solutions":["Ensure the signature contains all three fields separated by exactly ', ' (comma + space): 'name{baseType, orderable, [ancestors]}'.","Regenerate the signature via TypeSignature.toString() instead of writing it by hand.","If separators differ (e.g. ',' without space), fix the serializer; the parser requires the \", \" substring."],"exampleFix":"// before\n\"shop.customer_id{bigint,true,[]}\"   // no ', ' separators\n// after\n\"shop.customer_id{bigint, true, []}\"","handlingStrategy":"validation","validationCode":"// require ', ' separators between fields\nif (!signature.contains(\"{\")) throw new IllegalArgumentException(\"missing '{' in: \" + signature);\nint open = signature.indexOf('{');\nif (!signature.substring(open).contains(\", \")) {\n    throw new IllegalArgumentException(\"distinct type signature missing ', ' separators: \" + signature);\n}","typeGuard":"static boolean hasCommaSpaceSeparators(String sig) {\n    if (sig == null) return false;\n    int open = sig.indexOf('{');\n    return open >= 0 && sig.indexOf(\", \", open) > 0;\n}","tryCatchPattern":"try {\n    TypeSignature.parseTypeSignature(signature);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"expected ','\")) {\n        // regenerate from canonical serialization or reject input\n    } else throw e;\n}","preventionTips":["Use exactly comma+space ('\\\", \\\"') between distinct-type fields.","Build signatures with TypeSignature objects, not string concatenation.","Round-trip test signatures in CI."],"tags":["presto","type-signature","parsing","distinct-type"],"backgroundTag":"type-signature-parse-failure","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}