{"record":{"id":"40406f069a5fed2e","repo":"jeecgboot/JeecgBoot","slug":"illegal-character-after-s-charat-i","errorCode":null,"errorMessage":"Illegal character after '?': {s.charAt(i)}","messagePattern":"Illegal character after '\\?': (.+?)","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java","lineNumber":616,"sourceCode":"                }\n\n            } else {\n                throw new ParseException(\n                        \"Illegal characters for this position: '\" + sub + \"'\",\n                        i);\n            }\n            if (eval != -1) {\n                incr = 1;\n            }\n            addToSet(sval, eval, incr, type);\n            return (i + 3);\n        }\n\n        if (c == '?') {\n            i++;\n            if ((i + 1) < s.length()\n                    && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\\t')) {\n                throw new ParseException(\"Illegal character after '?': \"\n                        + s.charAt(i), i);\n            }\n            if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) {\n                throw new ParseException(\n                        \"'?' can only be specified for Day-of-Month or Day-of-Week.\",\n                        i);\n            }\n            if (type == DAY_OF_WEEK) {\n                if (!daysOfMonth.isEmpty() && daysOfMonth.last() == NO_SPEC_INT) {\n                    throw new ParseException(\n                            \"'?' can only be specified for Day-of-Month -OR- Day-of-Week.\",\n                            i);\n                }\n            }\n\n            addToSet(NO_SPEC_INT, -1, 0, type);\n            return i;\n        }","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java#L598-L634","documentation":"After a '?' character, the parser advances i and checks that the following character is a space or tab. If (i+1) < length and the char at i is not a space (and the char at i+1 is not a tab), this is thrown. '?' must stand alone as a whole field value, so any trailing non-whitespace like '?5' or '?*' is illegal.","triggerScenarios":"A '?' glued to another token: '0 0 0 ?5 * *' (dow '?5'), '0 0 0 * * ?*' (trailing '*'), or a '?' in the middle of a field like '0 0 0 ?-1 * *'. Note the condition is a logical AND of two checks, so single trailing non-space may or may not trip depending on the next char, but any non-whitespace directly after '?' in a multi-char field triggers it.","commonSituations":"Typing '?' next to other characters thinking it means 'any'; mixing '?' and '*' in the same field; malformed programmatic concatenation.","solutions":["Use '?' only as the complete field value - it must be the only token in that field.","Replace '?X' with either '?' (no specific value) or the explicit value 'X'.","Remember '?' is the counterpart to '*': use it in dom or dow to say 'do not care', required when the other of dom/dow is specified."],"exampleFix":"// before - '?' glued to a digit\nString cron = \"0 0 0 ?5 * ?\";  // Illegal character after '?': 5\n\n// after - '?' as whole field\nString cron = \"0 0 0 ? * ?\";","handlingStrategy":"validation","validationCode":"// '?' must be a standalone field value with no adjacent token.\npublic static String validateQuestionMarkField(String field) {\n    if (field == null) return null;\n    if (field.contains(\"?\") && !field.trim().equals(\"?\")) {\n        return \"'?' must be the whole field, found: \" + field;\n    }\n    return null;\n}","typeGuard":"public static boolean isStandaloneQuestionMark(String field) {\n    return field != null && field.trim().equals(\"?\");\n}","tryCatchPattern":"try {\n    new CronExpression(expr);\n} catch (ParseException e) {\n    if (e.getMessage().startsWith(\"Illegal character after '?'\")) {\n        return \"'?' must stand alone in its field; remove the trailing character. \" + e.getMessage();\n    }\n    throw e;\n}","preventionTips":["Enforce that any field containing '?' equals exactly '?'.","Treat '?' and '*' as mutually exclusive within a single field.","In the UI, present '?' as a toggle, not as a typable character alongside others."],"tags":["cron","xxl-job","wildcard","validation","parse-error"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}