theonedev/onedev · error · RuntimeException

Malformed action condition

Error message

Malformed action condition

What it means

Thrown by ActionCondition.syntaxError listener when the ANTLR lexer/parser fails to parse an action condition expression. It is a plain RuntimeException wrapping the ANTLR RecognitionException, meaning the condition text does not conform to the action condition grammar.

Source

Thrown at server-core/src/main/java/io/onedev/server/buildspec/job/action/condition/ActionCondition.java:82

	public static String getValue(String token) {
		return StringUtils.unescape(FenceAware.unfence(token));
	}
	
	@Override
	public boolean matches(Build build) {
		return criteria.matches(build);
	}
	
	public static ActionCondition parse(Job job, String conditionString) {
		CharStream is = CharStreams.fromString(conditionString); 
		ActionConditionLexer lexer = new ActionConditionLexer(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 action condition", e);
			}
			
		});
		CommonTokenStream tokens = new CommonTokenStream(lexer);
		ActionConditionParser parser = new ActionConditionParser(tokens);
		parser.removeErrorListeners();
		parser.setErrorHandler(new BailErrorStrategy());
		ConditionContext conditionContext = parser.condition();

		Criteria<Build> criteria;
		
		if (conditionContext.Always() != null) {
			criteria = new AlwaysCriteria();
		} else {
			criteria = new ActionConditionBaseVisitor<Criteria<Build>>() {
	
				@Override
				public Criteria<Build> visitParensCriteria(ParensCriteriaContext ctx) {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Read the wrapped RecognitionException (the 'Caused by' chain) for line/char position and offending symbol.
  2. Fix quoting: wrap string values in single quotes and escape embedded quotes.
  3. Verify parentheses are balanced and operators are spelled exactly as the grammar expects (e.g. previous build state names, field operator names).
  4. Use the condition builder/editor UI in OneDev instead of hand-writing the expression.

Example fix

// before
condition: this succeeded || previous build failed

// after (grammar-compliant syntax)
condition: this build is successful and previous build is failed
Defensive patterns

Strategy: try-catch

Validate before calling

// no public pre-parse validator; dry-run parse yourself
try {
    ActionCondition.parse(conditionText, job, build);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("Malformed action condition")) {
        // reject/repair conditionText before real use
    } else throw e;
}

Try / catch

try {
    ActionCondition.parse(text, job, build);
} catch (RuntimeException e) {
    throw new IllegalArgumentException("Invalid condition '" + text + "': " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Passing a syntactically invalid condition string to ActionCondition.parse — e.g. unbalanced quotes or parentheses, unknown tokens, misspelled operator keywords, or dangling expressions.

Common situations: Hand-editing the job condition in buildspec.yml; copying conditions from docs with wrong quoting; using an operator name not in the grammar; smart quotes from copy-pasting from editors.

Understand the failure class

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/aad3d1bb3b8339d5. Report an issue: GitHub.