{"record":{"id":"20d45ebacc329ebe","repo":"OtterMind/Chat2DB","slug":"invalid-snowflake-index-sort-direction-value","errorCode":null,"errorMessage":"Invalid Snowflake index sort direction: {value}","messagePattern":"Invalid Snowflake index sort direction: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-plugins/chat2db-community-snowflake/src/main/java/ai/chat2db/plugin/snowflake/SnowflakeSqlGuards.java","lineNumber":101,"sourceCode":"        if (expression.isEmpty()) {\n            throw invalid(\"cluster by clause\", value);\n        }\n        scanExpression(expression, CLAUSE_BREAKOUT_KEYWORDS, false, \"cluster by clause\");\n        return \"CLUSTER BY \" + expression;\n    }\n\n    /**\n     * Validate an index sort direction: only ASC/DESC are legal, returned in canonical uppercase.\n     */\n    public static String requireAscOrDesc(String value) {\n        String trimmed = StringUtils.trimToEmpty(value);\n        if (\"ASC\".equalsIgnoreCase(trimmed)) {\n            return \"ASC\";\n        }\n        if (\"DESC\".equalsIgnoreCase(trimmed)) {\n            return \"DESC\";\n        }\n        throw new IllegalArgumentException(\"Invalid Snowflake index sort direction: \" + value);\n    }\n\n    private static void scanExpression(String expression, Set<String> breakoutKeywords,\n                                       boolean allowTopLevelComma, String description) {\n        Deque<Character> delimiters = new ArrayDeque<>();\n        boolean sawContent = false;\n        for (int i = 0; i < expression.length(); i++) {\n            char c = expression.charAt(i);\n            if (c == '\\'' || c == '\"') {\n                i = scanQuoted(expression, i, c, description);\n                sawContent = true;\n                continue;\n            }\n            if (startsWith(expression, i, \"--\") || startsWith(expression, i, \"/*\")\n                    || startsWith(expression, i, \"*/\") || c == ';' || c == '\\n' || c == '\\r'\n                    || Character.isISOControl(c)) {\n                throw invalid(description, expression);\n            }","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-plugins/chat2db-community-snowflake/src/main/java/ai/chat2db/plugin/snowflake/SnowflakeSqlGuards.java#L83-L119","documentation":"Thrown by SnowflakeSqlGuards.requireAscOrDesc when the value is not ASC or DESC (case-insensitive). This validates index sort direction in Snowflake DDL generation, where only ascending and descending are legal. The method trims input and uses equalsIgnoreCase, so 'asc', 'Asc', 'ASC' all pass, but 'ASCENDING', 'ascending', 'A', or any other value fails.","triggerScenarios":"Calling SnowflakeSqlGuards.requireAscOrDesc(value) where value is null, blank, or not equal to ASC or DESC ignoring case. Common invalid values: 'ASCENDING', 'DESCENDING', 'ascending', '', null, 'A', 'D', 'asc/desc'.","commonSituations":"A UI dropdown or form field that allows free-text sort direction entry; metadata from a source that uses full words instead of abbreviations; a configuration typo; a default value that was never set (null or empty string).","solutions":["Normalize the input to 'ASC' or 'DESC' before calling requireAscOrDesc","Use a constrained UI control (radio button or dropdown) that only offers ASC/DESC choices","Default unset values to 'ASC' before validation"],"exampleFix":"// before\nSnowflakeSqlGuards.requireAscOrDesc(\"ASCENDING\");\n\n// after\nString direction = \"ASCENDING\".startsWith(\"ASC\") ? \"ASC\" : \"DESC\";\nSnowflakeSqlGuards.requireAscOrDesc(direction);","handlingStrategy":"validation","validationCode":"public static String normalizeSortDirection(String value) {\n    if (value == null || value.isBlank()) return \"ASC\";\n    String upper = value.trim().toUpperCase(Locale.ROOT);\n    if (upper.startsWith(\"ASC\")) return \"ASC\";\n    if (upper.startsWith(\"DESC\")) return \"DESC\";\n    throw new IllegalArgumentException(\"Sort direction must be ASC or DESC, got: \" + value);\n}","typeGuard":"public static boolean isValidSortDirection(String value) {\n    if (value == null) return false;\n    String trimmed = value.trim();\n    return \"ASC\".equalsIgnoreCase(trimmed) || \"DESC\".equalsIgnoreCase(trimmed);\n}","tryCatchPattern":null,"preventionTips":["Constrain UI inputs to a dropdown offering only ASC and DESC","Normalize common variants (ASCENDING, ascending) to canonical ASC/DESC before validation","Default unset values to ASC rather than passing null or empty"],"tags":["snowflake","ddl","validation","index"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}