{"record":{"id":"170a4f78ecd422cf","repo":"apache/dolphinscheduler","slug":"unsupported-placeholder-expression","errorCode":null,"errorMessage":"Unsupported placeholder expression: ","messagePattern":"Unsupported placeholder expression: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parser/TimePlaceholderUtils.java","lineNumber":293,"sourceCode":"        if (StringUtils.isEmpty(timeExpression)) {\n            if (ignoreInvalidExpression) {\n                return timeExpression;\n            }\n            throw new IllegalArgumentException(\"Cannot format the date\" + date + \" with null timeExpression\");\n        }\n        try {\n            if (timeExpression.startsWith(TIMESTAMP)) {\n                return calculateTimeStamp(timeExpression, date);\n            }\n            if (timeExpression.startsWith(YEAR_WEEK)) {\n                return calculateYearWeek(timeExpression, date);\n            }\n            return calcTimeExpression(timeExpression, date);\n        } catch (Exception e) {\n            if (ignoreInvalidExpression) {\n                return timeExpression;\n            }\n            throw new IllegalArgumentException(\"Unsupported placeholder expression: \" + timeExpression, e);\n        }\n    }\n\n    /**\n     * get week of year\n     * @param expression expression\n     * @param date       date\n     * @return week of year\n     */\n    private static String calculateYearWeek(final String expression, final Date date) {\n\n        String dataFormat = expression.substring(YEAR_WEEK.length() + 1, expression.length() - 1);\n\n        String targetDate = \"\";\n        try {\n\n            if (dataFormat.contains(COMMA)) {\n                String param1 = dataFormat.split(COMMA)[0];","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parser/TimePlaceholderUtils.java#L275-L311","documentation":"The catch-all in formatTimeExpression: any exception raised while evaluating a placeholder (bad syntax, unknown function, arithmetic errors from nested calculate(), or the RuntimeExceptions from calculateYearWeek/calcMonthBegin) is rethrown as IllegalArgumentException(\"Unsupported placeholder expression: ...\", e) when ignoreInvalidExpression is false. The expression was non-empty but does not match any supported time-placeholder grammar, or is malformed for the matched branch.","triggerScenarios":"formatTimeExpression(timeExpression, date, false) where timeExpression starts with $N, $Y, $M or similar but the inner expression is syntactically invalid (e.g. missing closing paren, non-numeric offset like $[yyyyMMdd+abc], a month-begin expression without exactly two comma-separated params, or a $[week(yyyymmww)] with a bad format). Any exception from calcTimeExpression / calculateYearWeek / calculateTimeStamp lands here.","commonSituations":"Typos in scheduler parameter expressions ($[add_months(yyMMdd,-1)] — wrong format token), missing parenthesis, arithmetic operators on non-numeric values, expressions copied from docs of a different scheduler version where the grammar changed.","solutions":["Verify the expression syntax against supported forms, e.g. $[yyyyMMdd], $[add_months(yyyyMMdd,-N)], $[month_begin(yyyyMMdd,N)], $[week_begin(yyyyMMdd,N)], $N, $Y","Inspect the cause chain (getCause) — the IllegalArgumentException wraps the real error (e.g. 'expression not valid', NumberFormatException)","Call with ignoreInvalidExpression=true to have invalid expressions returned unchanged instead of failing the task","Print/log the exact timeExpression string and test it in a unit test against TimePlaceholderUtils"],"exampleFix":"// before\nString result = TimePlaceholderUtils.formatTimeExpression(\"$[add_months(yyyyMMdd,-1x)]\", date, false);\n// throws: Unsupported placeholder expression: $[add_months(yyyyMMdd,-1x)]\n// after\nString result = TimePlaceholderUtils.formatTimeExpression(\"$[add_months(yyyyMMdd,-1)]\", date, false);","handlingStrategy":"try-catch","validationCode":"// Pre-check the expression against known prefixes and balanced parens\nboolean isPlausible(String e) {\n    if (e == null || e.isEmpty()) return false;\n    long opens = e.chars().filter(c -> c == '(').count();\n    long closes = e.chars().filter(c -> c == ')').count();\n    return opens == closes;\n}","typeGuard":null,"tryCatchPattern":"try {\n    return TimePlaceholderUtils.formatTimeExpression(expr, date, false);\n} catch (IllegalArgumentException e) {\n    Throwable cause = e.getCause();\n    log.error(\"Unsupported time placeholder '{}': {}\", expr, cause == null ? e.getMessage() : cause.getMessage());\n    throw new TaskException(\"Invalid time placeholder in task params: \" + expr, e);\n}","preventionTips":["Always inspect getCause() — the wrapper hides the real parse error","Copy expression grammar exactly from TimePlaceholderUtils constants (TIMESTAMP, YEAR_WEEK, MONTH_BEGIN, ...)","Use ignoreInvalidExpression=true when expressions may legitimately be non-time strings","Keep a table of supported expressions in project docs and lint task params against it"],"tags":["date","placeholder","invalid-expression","illegal-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}