Skip to content

Verifier crashes on a lambda whose parameter type cannot be resolved (classes not on the classpath) #396

Open

Description

@CatarinaGamboa

Impact: verification stops with an internal error on a lambda whose parameter type comes from a class that is not on the classpath: 2 of the 53 real-world files below.

Description

When a lambda is passed to a method of an unresolved type, Spoon cannot infer the lambda parameter's type, and RefinementTypeChecker.visitCtLambda adds the parameter with a null type: Context.addVarToContext then calls getSuperclass() on it (Context.java:193). Same null type in Context as #389 (there through addInstanceVariable, from a unary operator), reached from a different construct. A parameter with an unknown type could be added without supertypes.

Minimal reproducer (org.example.missing is not on the classpath)

import org.example.missing.Request;

public class Repro {
    static void print(Request request) {
        request.names().forEach(name -> System.out.println(name));
    }
}

Expected

Correct! Passed Verification. (with the usual "Java compilation encountered issues" warning).

Actual

Exception in thread "main" java.lang.RuntimeException: 
Error while checking CtMethodImpl
  on print(Request request) { 
  at Repro.java:4
  with 
Error while checking CtBlockImpl
  on { 
  at Repro.java:4
  with 
Error while checking CtInvocationImpl
  on request.names().forEach(name -> System.out.println(name)); 
  at Repro.java:5
  with 
Error while checking CtLambdaImpl
  on (name -> System.out.println(name)); 
  at Repro.java:5
  with Cannot invoke "spoon.reflect.reference.CtTypeReference.getSuperclass()" because "type" is null
...
Caused by: java.lang.NullPointerException: Cannot invoke "spoon.reflect.reference.CtTypeReference.getSuperclass()" because "type" is null
	at liquidjava.processor.context.Context.addVarToContext(Context.java:193)
	at liquidjava.processor.refinement_checker.RefinementTypeChecker.visitCtLambda(RefinementTypeChecker.java:423)

Reproduced on main at ad055b4 (liquidjava-verifier 0.0.35).

Real-world files that hit it

  • .forEach(header -> builder.withHeader(header, list(originalRequest.getHeaders(header)))); — atlassian/openapi-request-validator (file)
  • (e -> new StreamSource(e.getXsdAsStream())) — stvzhou/powsybl-core (file)

Context

Found while running LiquidJava on the original repository files of 53 real-world typestate and refinement bugs (the files our study exercises were simplified from). Each file is verified on its own, as a user would verify one file of a project, so the project's other classes and its dependencies are not on the classpath. Related: #388, #389, #390.

Activity

  1. CatarinaGamboa commented on Oct 27, 2026

    @CatarinaGamboa
    CollaboratorAuthor

    Two more real-world files that hit this on main at 0d489e1 (liquidjava-verifier 0.0.36), same frame (visitCtLambda → Context.addVarToContext):

    • r -> new AdmissionsServer(admissionsRouter.getClientIdentityProvider(), ...): Hellblazer/Delos (file)
    • rule -> !Boolean.TRUE.equals(rule.getAlwaysInContext()): open-metadata/OpenMetadata (file)

    With these, 6 of the 74 files (the 53 originals plus 21 fixed versions) stop here, more than any other crash except the array read in #425.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingreal-world-findingFound when experimenting liquidjava in real world repos or OSS

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions