theonedev/onedev · error · RuntimeException
Malformed retry condition
Error message
Malformed retry condition
What it means
Thrown by RetryCondition's ANTLR syntaxError listener when a retry condition string fails to parse against the retry condition grammar. It wraps the ANTLR RecognitionException in a RuntimeException, so the cause chain contains position and offending-symbol details.
Source
Thrown at server-core/src/main/java/io/onedev/server/buildspec/job/retrycondition/RetryCondition.java:78
@Override
public Predicate getPredicate(@Nullable ProjectScope projectScope, CriteriaQuery<?> query, From<RetryContext, RetryContext> from, CriteriaBuilder builder) {
throw new UnsupportedOperationException();
}
public boolean matches(RetryContext context) {
return criteria.matches(context);
}
public static RetryCondition parse(Job job, String conditionString) {
CharStream is = CharStreams.fromString(conditionString);
RetryConditionLexer lexer = new RetryConditionLexer(is);
lexer.removeErrorListeners();
lexer.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line,
int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("Malformed retry condition", e);
}
});
CommonTokenStream tokens = new CommonTokenStream(lexer);
RetryConditionParser parser = new RetryConditionParser(tokens);
parser.removeErrorListeners();
parser.setErrorHandler(new BailErrorStrategy());
ConditionContext conditionContext = parser.condition();
Criteria<RetryContext> criteria;
if (conditionContext.Never() != null) {
criteria = new NeverCriteria();
} else {
criteria = new RetryConditionBaseVisitor<Criteria<RetryContext>>() {
@Override
public Criteria<RetryContext> visitParensCriteria(ParensCriteriaContext ctx) {View on GitHub (pinned to d44925c47c)
Solutions
- Inspect the Caused-by RecognitionException for line/char and offending token.
- Fix quoting and keyword spelling per the retry condition grammar.
- Simplify the condition and rebuild it incrementally, testing after each addition.
Example fix
// before retry condition: error message contains 'connection reset' // after (valid quoting/syntax) retry condition: error message contains 'connection reset' && attempt < 3
Defensive patterns
Strategy: try-catch
Validate before calling
try {
RetryCondition.parse(conditionText);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("Malformed retry condition")) {
// surface RecognitionException details (line/char) for the author
} else throw e;
} Try / catch
try {
RetryCondition.parse(text);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
throw new IllegalArgumentException("Invalid retry condition '" + text + "': " + (cause != null ? cause.getMessage() : e.getMessage()), e);
} Prevention
- Incrementally build retry conditions and test-parse each addition.
- Use single quotes for string patterns; escape embedded quotes.
- Check the cause chain for the exact offending token.
When it happens
Trigger: A retry condition expression in the job spec with invalid syntax — misspelled keywords, unbalanced quotes, or tokens not in the grammar (e.g. bad operator names for 'error message'/'failure reason' criteria).
Common situations: Hand-writing retry conditions in buildspec.yml; quoting mistakes around error-message patterns; copy-paste artifacts like smart quotes.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed action condition
- Malformed log instruction
- Param not found:
- Malformed build spec (import project: {0}, import revision:
- Build spec not defined (import project: {0}, import revision
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/7f7db2b11e68baa2.
Report an issue: GitHub.