{"record":{"id":"6dc270a02884f9a5","repo":"quarkusio/quarkus","slug":"a-skippredicate-instance-may-not-be-serialized","errorCode":null,"errorMessage":"A skipPredicate instance may not be serialized","messagePattern":"A skipPredicate instance may not be serialized","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/scheduler/common/src/main/java/io/quarkus/scheduler/common/runtime/SyntheticScheduled.java","lineNumber":114,"sourceCode":"\n    @Override\n    public String executeWith() {\n        return implementation;\n    }\n\n    @Override\n    public String executionMaxDelay() {\n        return executionMaxDelay;\n    }\n\n    @Override\n    public String description() {\n        return description;\n    }\n\n    public String toJson() {\n        if (skipPredicate != null) {\n            throw new IllegalStateException(\"A skipPredicate instance may not be serialized\");\n        }\n        JsonObject json = new JsonObject();\n        json.put(\"identity\", identity);\n        json.put(\"cron\", cron);\n        json.put(\"every\", every);\n        json.put(\"delay\", delay);\n        json.put(\"delayUnit\", delayUnit.toString());\n        json.put(\"delayed\", delayed);\n        json.put(\"overdueGracePeriod\", overdueGracePeriod);\n        json.put(\"concurrentExecution\", concurrentExecution.toString());\n        json.put(\"timeZone\", timeZone);\n        json.put(\"executeWith\", implementation);\n        json.put(\"executionMaxDelay\", executionMaxDelay);\n        json.put(\"description\", description);\n        return json.encode();\n    }\n\n    public static SyntheticScheduled fromJson(String json) {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/scheduler/common/src/main/java/io/quarkus/scheduler/common/runtime/SyntheticScheduled.java#L96-L132","documentation":"SyntheticScheduled is the serializable description of a programmatically created @Scheduled method; toJson() flattens it to JSON for the build-time/CDI synthetic bean machinery. A skipPredicate configured as a live object instance cannot be represented in JSON, so toJson() throws this IllegalStateException if one is present.","triggerScenarios":"Serializing a SyntheticScheduled whose skipPredicate field is a non-null instance, i.e. a job definition built with setSkipPredicate(instance) rather than a class name, then having its metadata converted to JSON (e.g. recorded synthetic bean output).","commonSituations":"Using a Lambda or prebuilt SkipPredicate object in a programmatically scheduled job and then serializing the schedule (Quartz job-store persistence or build-time recording); moving from skip predicate classes to instances across versions.","solutions":["Configure the skip predicate as a Class (setSkipPredicate(Class)) so the JSON can reference it by name instead of an instance","Avoid serializing SyntheticScheduled with instance-based predicates; register the predicate as a CDI bean and reference its class","If persistence of job metadata is required, ensure predicates are class-referenced before toJson() is invoked"],"exampleFix":"// before\njobDef.setSkipPredicate(new MySkipPredicate()); // instance -> not serializable\n// after\njobDef.setSkipPredicate(MySkipPredicate.class);","handlingStrategy":"validation","validationCode":"if (synthetic != null && syntheticHasInstanceSkipPredicate(synthetic)) {\n    throw new IllegalStateException(\"use setSkipPredicate(Class) for serializable schedules\");\n}","typeGuard":"boolean serializableSchedule(SyntheticScheduled s) {\n    return s.skipPredicateClass() != null; // class-referenced predicate, not an instance\n}","tryCatchPattern":"try {\n    json = synthetic.toJson();\n} catch (IllegalStateException e) {\n    LOG.error(\"Schedule uses an instance skipPredicate; switch to a Class reference\", e);\n}","preventionTips":["Always configure skip predicates via Class references, not instances/lambdas","Register predicates as CDI beans and reference their classes","Avoid serializing synthetic schedules that hold live objects","Keep predicate classes no-arg constructible for later instantiation"],"tags":["scheduler","serialization","skip-predicate","synthetic-bean"],"backgroundTag":"not-serializable","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}