karatelabs/karate · error · RuntimeException

no step parsed

Error message

no step parsed

What it means

ScenarioRuntime parses a raw text snippet by wrapping it in a synthetic feature (`Feature:\nScenario:\n` + text). If the Gherkin parser yields no sections at all, the runtime throws "no step parsed" because nothing usable was provided.

Solutions

  1. Log the exact `trimmed` string before invoking the runtime and ensure it is a non-empty step line like `* print 'hello'`
  2. Trim away Gherkin comments and tags so at least one real step remains
  3. Guard upstream: only call the eval API when the input passes a non-blank, non-comment check

Example fix

// before
runtime.evalText(optionalStepText);
// after
String t = optionalStepText == null ? "" : optionalStepText.strip();
if (t.isEmpty() || t.startsWith("#") || t.startsWith("@")) {
    throw new IllegalArgumentException("step text required");
}
runtime.evalText(t);
Defensive patterns

Strategy: validation

Validate before calling

String t = stepText == null ? "" : stepText.strip();
if (t.isEmpty() || t.lines().allMatch(l -> l.strip().isEmpty() || l.strip().startsWith("#") || l.strip().startsWith("@"))) {
    throw new IllegalArgumentException("step text must contain at least one step");
}

Type guard

static boolean hasParseableStep(String s) {
    return s != null && s.lines().anyMatch(l -> {
        String t = l.strip();
        return !t.isEmpty() && !t.startsWith("#") && (t.startsWith("*") || t.matches("(Given|When|Then|And|But)\\b.*"));
    });
}

Try / catch

try { runtime.evalText(text); } catch (RuntimeException e) { if (e.getMessage().equals("no step parsed")) { throw new IllegalArgumentException("empty or non-step input: " + text); } throw e; }

Prevention

When it happens

Trigger: Calling the API that evaluates a step/feature text with an empty or whitespace-stripped `trimmed` string, or text containing only comments/tags such that Feature.read returns zero sections.

Common situations: Passing an empty string variable to dynamic step evaluation; reading step text from an external source (file, env var, DB) that came back blank; building Gherkin programmatically and emitting only `Background:` or comments.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/72238b8773788497. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:1512

        long startTime = System.currentTimeMillis();
        String trimmed = text == null ? "" : text.trim();
        boolean hasPrefix = false;
        for (String prefix : Step.PREFIXES) {
            if (trimmed.startsWith(prefix)) {
                hasPrefix = true;
                break;
            }
        }
        if (!hasPrefix) {
            trimmed = "* " + trimmed;
        }
        Step parsed;
        Scenario synthScenario;
        try {
            Resource resource = Resource.text("Feature:\nScenario:\n" + trimmed);
            Feature feature = Feature.read(resource);
            if (feature.getSections().isEmpty()) {
                throw new RuntimeException("no step parsed");
            }
            synthScenario = feature.getSection(0).getScenario();
            if (synthScenario == null || synthScenario.getSteps() == null || synthScenario.getSteps().isEmpty()) {
                throw new RuntimeException("no step parsed");
            }
            parsed = synthScenario.getSteps().get(0);
        } catch (Exception e) {
            Step fakeStep = new Step(scenario, -1);
            return StepResult.failed(fakeStep, startTime, 0, e);
        }
        Step fakeStep = new Step(synthScenario, -1);
        fakeStep.setLine(parsed.getLine());
        fakeStep.setEndLine(parsed.getEndLine());
        fakeStep.setPrefix(parsed.getPrefix());
        fakeStep.setKeyword(parsed.getKeyword());
        fakeStep.setText(parsed.getText());
        fakeStep.setDocString(parsed.getDocString());
        fakeStep.setDocStringLine(parsed.getDocStringLine());

View on GitHub (pinned to a22eb90246)